编程文汇

jnr-ffi: java调用windows dll linux so的更简便方法

JAVA调用c之痛

为什么要调用c呢,因为跨平台的代码不想重复写,bug不想重复改,各开发语言的细微差别出的bug需要大量精力去调试,所以此时调用同一份代码省掉的工作量是巨大的。JNI是在太麻烦了,需要再把现有库的所有暴露接口再封装一遍。在 openJdk Panama项目完工之前,代替JNI的最佳方式应该就是JNR了,简便与效率并重,效率最接近JNI的一种。

实际测试

在使用之前,我翻看了所有文档,也没弄明白它怎么使用:c代码那块要怎么写??

既然文档里没有,我就亲自动手试了一把,自己手里有一个县城的dll库,导出了获取当前utc时间的函数:
double64 ezg_Now()

我就先试试能不能直接调用它:
把它(ezg.dll)拷贝到我的eclipse工程的根目录下,好让加载的时候能直接搜索到。

public class Native {
public static interface LibC {
  double ezg_Now();
}

public static void main(String[] args) {
  LibC libc = LibraryLoader.create(LibC.class).load("ezg");

  System.out.println(libc.ezg_Now());
}
}

运行测试了一下,没有出任何错误,顺利执行成功。

JNR使用流程

现在明白了:只要是正常的dll它都能调用,不需要任何额外工作,前提是把参数和返回值数据类型正确匹配。

  1. 正常编写c,导出函数,不需要做任何额外工作
  2. java中编写接口,声明导出的函数
  3. 加载dll,即可调用。

与JNI相比,真是方便。
另外JNA用起来也比较方便,但是效率要低一个量级。