Java通过JNI调用dll库函数
由于接手了一个项目,尝试通过Java调用dll库函数。虽然只差最后一步就成功了,还是记录下过程吧。
References:
- https://support.microsoft.com/en-us/help/222092 MS官方文档,必看
- https://blog.csdn.net/happyboylk/article/details/51902685
- https://stackoverflow.com/questions/8113080/cant-load-ia-32-bit-dll-on-a-amd-64-bit-platform
- http://blog.sina.com.cn/s/blog_79ba23780101gpiv.html JNA
如果dll文件还没生成,那应该先写Java的本地方法接口,生成相应的.h头文件,再写实现方法,并生成dll。但是如果是别人开发好的dll,只能另外写一个dll共享库,使用SUN规定的数据结构替代C语言的数据结构,调用已有的dll函数。然后再在Java中载入这个适配器dll使用。比较繁琐,由于之前没做过这种事,所以这里先测试下看看JNI是否行得通。于是找了一些文档写个Demo试试。
根据MS的文档一直走,还是比较简单的。但是文档有些命令不一致,而且注意事项也没说明。
简单的翻译:
- 确保您使用的微软的Java SDK版本支持JNI。JNI支持从1998年12月SDK版本3.1开始及以上。
- 确保环境变量、CLASSPATH中包含一个指向"[WINDIR]\Java\Classes\Classes.zip"和"C:"的引用。(假设C:是你开发环境盘)。
- 确保你的"[SDK-Java]\Bin"目录包含在你的路径(JavaH,JVC,JView)。(注:命令应该是javah、javac、java)
- 确保Visual c++正确地设置为使用命令行。有关详细信息,请参阅您的Visual c++文档。
Java代码如下:
public class TestJNI { public native void greetings(); static { System.loadLibrary("greet"); } public static void main(String args[]) { new TestJNI().greetings(); } }
编译Java文件
jvc TestJNI.java (注:javac)
运行JavaH以生成class:
javah -jni TestJNI
自动生成的TestJNI.h如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class TestJNI */ #ifndef _Included_TestJNI #define _Included_TestJNI #ifdef __cplusplus extern "C" { #endif /* * Class: TestJNI * Method: greetings * Signature: ()V */ JNIEXPORT void JNICALL Java_TestJNI_greetings (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
根据生成的头文件实现相应的接口函数,C++实现如下:
#include "TestJNI.h" #include <stdio.h> JNIEXPORT void JNICALL Java_TestJNI_greetings(JNIEnv *env,jobject jobj) { printf("Hello from Visual C++!"); }
编译C/C++文件
cl greet.cpp -Ic:\sdk-java.31\include -Fegreet.dll -MD -LD (命令需要用VS开发人员提示符 Developer Command Prompt for VS 20XX)
测试程序
jview TestJNI (注:java)
命令执行如下
cl编译C/C++文件时,需要将相应头文件从jdk目录下复制到vs目录下,可查看第二条参考链接
在最后运行Java类文件时,提示64位的jvm只能调用64位的dll,wtf!鬼特么知道dll是多少位的,就算调用成功,还指不定多少坑要踩。放弃,换个方法。