从Java调用Win32 API方法

时间:2010-03-05 18:53:33

标签: java winapi java-native-interface

我需要从Java程序中调用some methods in Wininet.dll

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

我知道这涉及JNI,但我究竟如何做到这一点?我需要在Wininet.h上调用javah吗?我在哪里可以获得Wininet.h的副本?指向现有详细教程的指针就足够了。

3 个答案:

答案 0 :(得分:42)

  1. JNA似乎是你想要的the industry standard,“Java程序可以轻松访问本机共享库(Windows上的DLL),而无需编写除Java代码之外的任何内容 - JNI或本机代码是必需的“

  2. 还有Java Foreign Function Interface - example usage
    如果你没问题,你可以embed JRuby解释员并通过jruby-ffi通过here调用winapi,这样会更容易,请参阅herehere和{ {3}}

答案 1 :(得分:13)

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

首先你上课。这是一个例子:

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 */
}

然后使用JDK中的一个命令,它将自动获取您的类并生成.h和.c文件。命令是“javah”。方法签名看起来像这样:

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

在.c文件中,您可以包含所需的任何Windows标头,并充实该方法。

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...
}

非常重要您不重命名该方法,这就是它与您的特定类相关联的方式。

一旦获得了,就将这些文件编译成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

这将产生一些文件,包括JNIHelper.dll,这就是我命名的DLL。

此时,你基本上已经完成了。您可以正常使用Java类,并在调用静态方法时运行Win32代码。您所要做的就是导入库。在代码的某处(我把它放在我班级的静态块中)你需要这一行:

System.loadLibrary("JNIHelper");

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

就是这样。这是一堆样板,但如果你做一些简单的包装,那很简单。如果你必须处理Java类型或分配内存,它会变得更糟(注意:我没有,所以我没有经验)。

有一个完整的教程here(我今天首先发现它看起来不错,你可以在网上找到其他人。关于JNI的Wikipedia文章也有更多的信息。

希望这有帮助。

答案 2 :(得分:3)

无法直接调用本机库:这是因为Java Native Interface不支持方法中的某些参数。

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

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

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

GlueGen需要一个头文件,一个ANSI C编译器等

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

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