1.首先要在项目中加入jna依赖
compile group: 'net.java.dev.jna', name: 'jna', version: '4.5.0'
使用jna的优点是,我们不用了解C函数的实现,也不用写任何的C语言代码,就能调用到C函数。
2.写一个继承com.sun.jna.Library接口的接口,并声明要调用的C函数的方法,如
public interface CLibrary extends Library {
void testCal(double[] param, int version , double[] out);
}
我打算调用C函数中的testCal(double[] param, int version)方法,则在接口中声明即可。这其实就是个java的接口,方法的具体实现在C函数中进行,而接口实例化由jna来完成。
3.测试
public static void main(String[] args) {
//C编译的文件,windows为dll,linux为so文件
String dllPath = "C:/Users/Administrator/Desktop/testc.dll";
//加载文件,实例化接口
CLibrary cLibrary = Native.loadLibrary(dllPath , CLibrary.class);
double[] ins = new double[]{1,2,3,4,5,6,7,8};
double[] outs = new double[20];
//调用C方法
cLibrary.testCal(ins, 0x0500, outs );
System.out.println(Arrays.toString(outs));
}
整个过程不用写任何的C代码,当然,除非C函数也是由你负责写。
4.问题
在linux系统中,当调用两个以上的C函数,且函数中又有相同的方法时,会出现问题
例如,我有一个C文件test1.c :
#include <stdio.h>
int inmethod() {
return 100;
}
int outmethod() {
return 1 + inmethod();
}和test2.c :
#include <stdio.h>
int inmethod() {
return 200;
}
int outmethod() {
return 2 + inmethod();
}
编译打包好后为test1.so和test2.so
同时加载两个so文件,并调用两个文件的outmethod(),结果分别为
101 // OK
102 // 在我们的预想中,这里应该返回 202,但是现在却返回102
以上问题的原因在于C的符号表发生冲突,同名全局变量也会有这种问题。
解决方法有两个:
(1)让文件的提供者改写方法名和变量名,当然这得慢慢说服他了。
(2) Native.loadLibrary()允许传入一个参数RTLD_LOCAL,这个参数和平台有关,不同平台可能不同。