从 Java 调用 Win32 API 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2389156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:52:17  来源:igfitidea点击:

Calling Win32 API method from Java

javawinapijava-native-interface

提问by Paul Reiners

I need to call some methods in Wininet.dllfrom a Java program.

我需要从 Java 程序调用Wininet.dll 中的一些方法

I can find plenty of tutorials on how to call a new DLL that I create from Java, but I can't seem to find any tutorials on how to call an already existing DLL from Java.

我可以找到很多关于如何调用我从 Java 创建的新 DLL 的教程,但我似乎找不到任何关于如何从 Java 调用已经存在的 DLL 的教程。

I know this involves JNI, but how, exactly, do I do this? Do I need to call javahon Wininet.h? Where do I get a copy of Wininet.h? A pointer to an existing, detailedtutorial would be sufficient.

我知道这涉及到 JNI,但是我究竟该怎么做呢?我需要调用javahWininet.h 吗?在哪里可以获得 Wininet.h 的副本?指向现有的详细教程就足够了。

采纳答案by clyfe

  1. JNAseems the industry standardof what you want, "provides Java programs easy access to native shared libraries (DLLs on Windows) without writing anything but Java code—no JNIor native code is required"

  2. There is also Java Foreign Function Interface- example usage
    If is ok for you, you could embedthe JRubyinterpreter and call winapi via jruby-ffiwich is a lot easier, see here, here, and here

  1. JNA似乎是您想要的行业标准,“提供 Java 程序轻松访问本机共享库(Windows 上的 DLL),而无需编写除 Java 代码以外的任何内容——不需要JNI或本机代码”

  2. 也有Java的外交功能接口- 例如使用
    。如果是对你合适,你可以嵌入JRuby中通过解释和呼叫WINAPI JRuby的FFI至极是轻松了很多,看到这里这里这里

回答by Pindatjuh

One cannot directly call native libraries: this is because some arguments in methods are not supported by the Java Native Interface.

不能直接调用本地库:这是因为 Java 本地接口不支持方法中的某些参数。

There is something called GlueGen, this will create a seperate binary which will dynamically link against your native DLL. The generated binary is compatible with the JNI and thus callable from Java.

有一种叫做 GlueGen 的东西,这将创建一个单独的二进制文件,它将动态链接到您的本机 DLL。生成的二进制文件与 JNI 兼容,因此可以从 Java 调用。

http://en.wikipedia.org/wiki/Gluegen

http://en.wikipedia.org/wiki/Gluegen

To get a header-file for wininet.dll, you probably need to have the Platform SDK (or Windows SDK, newest version). You can also search the net for an online repository containing this header-file.

要获取 wininet.dll 的头文件,您可能需要有 Platform SDK(或 Windows SDK,最新版本)。您还可以在网络上搜索包含此头文件的在线存储库。

GlueGen will need a header-file, a ANSI C compiler, etc.

GlueGen 将需要一个头文件、一个 ANSI C 编译器等。

There is also a less known library called NativeCall, which doesn't require GlueGen. It already has binaries which are Java compatible. This is obviously slower, since it will load the DLL dynamically upon request from Java. I haven't used this, yet, but it sounds promising:

还有一个不太知名的库叫做 NativeCall,它不需要 GlueGen。它已经有与 Java 兼容的二进制文件。这显然更慢,因为它会根据 Java 的请求动态加载 DLL。我还没有使用过这个,但听起来很有希望:

http://johannburkard.de/software/nativecall/

http://johannburkard.de/software/nativecall/

回答by MBCook

I had to do this a little while ago. You'll need a C compiler and the Windows header files. I used mingw because it's free and I was only compiling one little file.

不久前我不得不这样做。您将需要一个 C 编译器和 Windows 头文件。我使用 mingw 是因为它是免费的,而且我只编译了一个小文件。

First you make your class. Here is an example:

首先你要上课。下面是一个例子:

package org.whatever.thingy;

public class MyClass {
    // Here is a JNI method, identified by 'native'

    public static native callWin32Thingy(int x, int y, boolean z);

    /* At this point, normal class stuff, other methods, variables, whatever */
}

You then use one of the commands that comes in the JDK, which will automatically take your class and generate .h and .c files. The command is "javah". The method signature will look something like this:

然后使用 JDK 中的命令之一,它会自动获取您的类并生成 .h 和 .c 文件。命令是“javah”。方法签名将如下所示:

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy
    (JNIEnv *, jclass, jint, jint, jboolean);

In the .c file, you include whatever windows headers you need, and flesh out the method.

在 .c 文件中,您包含您需要的任何窗口标题,并充实该方法。

JNIEXPORT void JNICALL Java_com_whatever_1thingy_MyClass_callWin32Thingy
    (JNIEnv *a, jclass b, jint c, jint d, jboolean e) {
    // Prep steps....

    Win32MethodCallWeCareAbout(x, y, z, hWhatever);

    // Cleanup stuff...
}

It's very importantyou don't rename the method, that's how it gets associated with your specific class.

这是非常重要的,你不要重命名方法,这就是它被如何与您的特定类关联。

Once you've got that, you compile those files into a DLL. Here are the commands I used for mingw, you'll have to adjust classes/paths/etc.

一旦你有了它,你就可以将这些文件编译成一个 DLL。这是我用于 mingw 的命令,您必须调整类/路径/等。

c:/MinGW/bin/gcc -c -Ic:/MinGW/include -I"c:/Program Files/Java/jdk1.5.0_12/include"
    -I"c:/Program Files/Java/jdk1.5.0_12/include/win32" -D__int64="long long"
    com_whatever_thingy_MyClass_JNIHelper.c

c:/MinGW/bin/gcc -shared -o JNIHelper.dll
    com_whatever_thingy_MyClass_JNIHelper_JNIHelper.o
    -Wl,--add-stdcall-alias,--kill-at,--output-def,def_file

This will produce some files, including JNIHelper.dll, which is what I named my DLL.

这将生成一些文件,包括 JNIHelper.dll,我将其命名为 DLL。

At this point, you're basically done. You use your Java class as normal, and it will run your Win32 code when you call the static method. All you have to do is import the library. Somewhere in your code (I put it in a static block in my class) you'll need this line:

到这一步,你就基本完成了。您可以照常使用 Java 类,当您调用静态方法时,它将运行您的 Win32 代码。您所要做的就是导入库。在你的代码中的某个地方(我把它放在我班级的一个静态块中)你需要这一行:

System.loadLibrary("JNIHelper");

This will cause Java to load the library named "JNIHelper.dll" and link it into the code. It has to be somewhere in the library path that Java knows about.

这将导致 Java 加载名为“JNIHelper.dll”的库并将其链接到代码中。它必须位于 Java 知道的库路径中的某个位置。

That's it. It's a bunch of boilerplate, but if you're doing some simple wrapping, it's easy. If you have to deal with Java types or allocating memory, it gets worse (note: I didn't, so I don't have experience there).

就是这样。这是一堆样板文件,但如果您正在做一些简单的包装,那就很容易了。如果您必须处理 Java 类型或分配内存,情况会变得更糟(注意:我没有,所以我没有这方面的经验)。

There's a whole tutorial here(first I found today that looked decent, and you can find others on the web. The Wikipediaarticle on JNI has more info too.

有一个完整的教程在这里(第一我今天看起来体面的发现,你可以在网络上找到他人。在维基百科上JNI文章有更多的信息了。

Hope this helps.

希望这可以帮助。