Java的JNA调用C++的So动态链接库
JNA简介
先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即可。首先看下JNI调用C/C++的过程,注意写程序时自下而上,调用时自上而下
那么JNA是什么呢?
JNA(Java Native Access)是一个开源的Java框架,是Sun公司推出的一种调用本地方法的技术,是建立在经典的JNI基础之上的一个框架。之所以说它是JNI的替 代者,是因为JNA大大简化了调用本地方法的过程,使用很方便,基本上不需要脱离Java环境就可以完成。
如果要和上图做个比较,那么JNA调用C/C++的过程大致如下
JNA技术原理
JNA使用一个小型的JNI库插桩程序来动态调用本地代码。开发者使用Java接口描述目标本地库的功能和结构,这使得它很容易利用本机平台的功能,而不会产生多平台配置和生成JNI代码的高开销。这样的性能、准确性和易用性显然受到很大的重视。
此外,JNA包括一个已与许多本地函数映射的平台库,以及一组简化本地访问的公用接口。
注意:
JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。
原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。
JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射,你不再需要编写C动态链接库。
也许这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。但总体影响不大,因为JNA也避免了JNI的一些平台配置的
JNA链接
https://github.com/java-native-access/jna
JNA Examples
https://www.eshayne.com/jnaex/index.html?example=2
JNA demo
编写So
#include<stdio.h>
#ifdef _WIN32
#define EXPORT_API extern "C" __declspec(dllexport)
#else
#define EXPORT_API extern "C" __attribute__ ((visibility("default")))
#endif
EXPORT_API int add(int a,int b) {
int c = a + b ;
return c ;
}
gcc -fpic -c test.c
gcc -shared -o libtest.so test.o
ls看一下生成的文件:
libtest.so test.c test.o
JNA在找so文件的时候,要匹配前缀为lib的so文件
设置JNA的jar包
https://www.cnblogs.com/chenjfblog/p/7943575.html
编写Java
import com.sun.jna.Library;
import com.sun.jna.Native;
public class TestSo {
public interface LgetLib extends Library {
// 调用linux下面的so文件,注意,这里只要写test就可以了,不要写libtest,也不要加后缀
LgetLib INSTANCE = (LgetLib) Native.loadLibrary("test",LgetLib.class);
int add(int a,int b);
}
public int add(int a,int b){
return LgetLib.INSTANCE.add(a,b);
}
public static void main(String[] args) {
TestSo ts = new TestSo();
int c = ts.add(10,20);
System.out.println("10+20="+c);
}
}
参考链接
https://github.com/java-native-access/jna
https://www.eshayne.com/jnaex/index.html?example=2
https://www.cnblogs.com/lanxuezaipiao/p/3635556.html
http://www.itnoteshare.com/note/129/publicNoteDetail.htm