Java 调用 DLL 无非三种方法:JNI、JNA、JNative
1 JNA是什么
JNA(JavaNativeAccess)框架是一个开源的Java框架,是SUN公司主导开发的,建立在
经典的JNI的基础之上的一个框架。
JNA项目地址:https://jna.dev.java.net/
JNA使Java调用原生函数就像.NET上的P/Invoke一样方便、快捷。
JNA的功能和P/Invoke类似,但编写方法与P/Invoke截然不同。JNA没有使用Annotation,
而是通过编写一般的Java代码来实现。
P/Invoke是.NET平台的机制。而JNA是Java平台上的一个开源类库,和其他类库没有
什么区别。只需要在classpath下加入jna.jar包,就可以使用JNA。
JNA使Java平台可以方便地调用原生函数,这大大扩展了Java平台的整合能力。
2 新建项目,添加依赖
快速搭建一个springboot 项目,在pom文件中加入
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>3.0.9</version>
</dependency>
3 Java 代码调用
首先看dll文件中定义的函数
//dll 文件中初始化函数
int INIT(char * pErrMsg)
新建一个类,类中新增下面接口 ,SiInterface 为dll文件,可以去掉后缀.dll
public interface SiInterface extends Library {
// DLL文件默认路径为项目根目录,若DLL文件存放在项目外,请使用绝对路径。(此处:(Platform.isWindows()?"SiInterface":"c")指本地动态库msvcrt.dll)
SiInterface INSTANCE = (SiInterface) Native.loadLibrary( "SiInterface.dll",
SiInterface.class);
// 声明将要调用的DLL中的方法
public int INIT(byte[] input);
}
main方法测试
public static void main(String[] args) throws Exception {
//INIT函数,参数是一个char*类型的可读写参数,需要用byte[]类型
byte[] outData = new byte[2048];
int code = SiInterface.INSTANCE.INIT(outData);
System.out.println(code);
String result = Native.toString(outData,"gbk");
System.out.println(result);
}
至此,调用dll的编码工作已经完成,是不是很简单 ,这都是sun公司大佬写的jna框架好用,但实战中其实会出现一些问题,下面总结一下
问题总结:
1 :java jna 报错:Unable to load library
这个错真让人头大,这个错误很明显是无法加载到指定的动态链接库,但是为什么无法加载确没有具体显示出来,是路径不对呢,还是dll的平台与当前jvm的平台不匹配没有在错误信息中显示出来。所以需要一步一步排除找原因。
1)首先你要明确知道这个dll动态链接库是32位的还是64位的编译的,与之对应的就是你的java版本也是要对应的32位或者64位的。
2)确认了第一点那么基本的环境就没问题了,然后是填写路径,一般路径可以是填相对路径还是绝对路径,为了避免可能出现未知错误,强烈建议还是填写绝对路径,绝对路径要是反斜杠"\",为了避免出错可以直接在IDE工具里面找到对应的dll文件右键copy path
粘贴到加载dll路径的方法里作为参数,效果如下图2.2
3)前面两步如果可以保证正确的话,那么基本上是可以加载成功的,如果还是失败那请再回去验证前面的步骤,如验证j程序运行是不是在你预期的jvm之上
点击运行程序看看当前运行的jdk版本是哪一个,如下图3.1
图3.1
接下来就是cmd,运行java -version,看下图3.2所示的jdk版本是32位,未显示默认32位的,还是64位。jdk版本一致,且是64位,那么与我的dll是相同的平台,
那么可以验证下dll是不是64位或者32位就好了,验证方法自行百度或者参照这位博主的https://www.cnblogs.com/Czhenyu/p/6439383.html
最后就是路径问题了,如果你是按照我的操作来的那么路径就不会有问题,应该是正常运行的。
4)到这一步,你的程序还是无法加载dll文件的话,我只能提供思路就是,你的dll是否还引用了其它的dll文件,其它的dll文件的平台与当前不一致。或者找你得到dll来源,确认这个dll是否可以用,dll文件时可以用visual studio 2017或其它把版本工具用C#代码直接引用调用的,当然你也可以用哪个工具打包一个dll。
查看dll文件位数还有一个简便方法(当然可以问提供dll文件之人最快,人家开发的嘛):
用txt或notepad 以记事本的方式打开,乱码没关系,如果第二段PE 后面那个为L ,则是32位的,否则为64位 ,
最后总结一下:1.平台要一致,平台要一致,平台要一致,重要的事情说三遍。
2.路径问题,最好是绝对路径。
剩下就是接口业务问题, 等待你的又是漫长的调试。。。。。。。