有些开发场景需要调用第三方c/c++的动态库,jdk本身有jni可以实现调用,但是jni的使用非常麻烦,这里提供另一个神器JNA。JNA(Java Native Access)是建立在JNI(Java Native Interface,Java本地调用)技术之上的Java开源框架,使用JNA开发后无需编写任何Native/JNI代码,只需在Java接口中描述目标Native Library的函数与结构,JNA会自动实现Java接口到Native Library的映射,可以方便地使用Java直接访问动态链接库中的函数。
一、制作动态库
1、编写c语言源代码
头文件mydylib.h
#ifndef MYDYLIB_H
#define MYDYLIB_H
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int get_rand(int a,int b,char* opt);
#endif
c语言源码mydylib.c
#include "mydylib.h"
int get_rand(int a,int b,char* opt)
{
if(*opt == '+')
{
return a+b;
}
if(*opt == '-')
{
return a*b;
}
if(*opt == '*')
{
return a*b;
}
if(*opt == '/')
{
return a/b;
}
return 0;
}
2、编译动态库
生成.o文件
gcc -Wall -c mydylib.c -o mydylib.o
生成动态库
# linux环境
gcc -shared -fPIC -o mydylib.so mydylib.o
#win环境
gcc -shared -fPIC -o mydylib.dll mydylib.o
二、集成JNA
JNA集成非常简单,只将坐标依赖加入pom.xml中即可
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.14.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.14.0</version>
</dependency>
三、JNA调用动态库
public interface MyDyLibrary extends Library{
boolean IS_LINUX= System.getProperty("os.name").contains("Linux");
/// 动态库路径
String DY_FILE = IS_LINUX?"mydylib.so":"mydylib.dll";
/// 加载动态库
MyDyLibrary INSTANCE = Native.load(DY_FILE, MyDyLibrary .class);
/**
* 映射动态库函数,此处的方法重载必须与动态库函数中头文件的函数声明一致,
* 关数据类型的匹配,下面会专门列出来
* @param a
* @param b
* @param opt
* @return
*/
int get_rand(int a,int b,String opt);
}
调用测试
int r1 = MyDyLibrary.INSTANCE.get_rand(50, 5, "+");
int r2 = MyDyLibrary.INSTANCE.get_rand(50, 5, "-");
int r3 = MyDyLibrary.INSTANCE.get_rand(50, 5, "*");
int r4 = MyDyLibrary.INSTANCE.get_rand(50, 5, "/");
System.out.println("r1="+r1);
System.out.println("r2="+r2);
System.out.println("r3="+r3);
System.out.println("r4="+r4);
四、类型映射表
由于跨语言调用,数据类型存在差异,JNA官方提供了类型映射表