记一次jna调研成果,动机是公司开始做一个公安交通方面的项目,对接华为以及大华时,他们提供的sdk基本都是函数库,所以才有了这次“轰轰烈烈”的调研。
因为目前这方面的资料比较少,所以在调研过程中还是踩了不少坑,将这次成果记录下来,有需要的人可以借鉴一下,基本能满足需要
jna简述
JNA全称Java Native Access,是一个建立在经典的JNI技术之上的Java开源框架。
JNA提供工具用于调用c/c++动态函数库(如Window的dll以及linux的so)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标函数库的函数与结构,JNA将自动实现Java接口方法到函数的映射
jna&c++数据类型对照
java类型 | c++类型 | 原生表现 |
---|---|---|
boolean | int | 32位整数(可定制) |
byte | char | 8位整数 |
char | wchar_t | 平台依赖 |
short | short | 16位整数 |
int | int | 32位整数(可定制) |
long | ong long, __int64 | 64位整数 |
float | float | 32位浮点数 |
double | double | 64位浮点数 |
Buffer/Pointer | pointer | 平台依赖(32或64位指针) |
[] (基本类型的数组) | pointer/array | 2或64位指针(参数/返回值) 邻接内存(结构体成员) |
String | char* | 0结束的数组 (native encoding or jna.encoding) |
WString | wchar_t* | /0结束的数组(unicode) |
String[] | char** | /0结束的数组的数组 |
WString[] | wchar_t** | /0结束的宽字符数组的数组 |
Structure | struct*/struct | 指向结构体的指针(参数或返回值) (或者明确指定是结构体指针)结构体(结构体的成员) (或者明确指定是结构体) |
Union | union | 等同于结构体 |
Structure[] | struct[] | 结构体的数组,邻接内存 |
Callback | (*fp)() | Java函数指针或原生函数指针 |
NativeMapped | varies | 依赖于定义 |
NativeLong | long | 平台依赖(32或64位整数) |
PointerType | pointer | 和Pointer相同 |
使用示例
环境说明:
- jna-version:5.2.0
- jdk-version:1.8
- c++version:c++11
- java开发使用idea
- c++开发使用clion
- g++版本自选
- 下面是jna的maven坐标,也可以将jar下载到本地使用
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.2.0</version>
</dependency>
1、简单调用
实现步骤
- 创建一个接口TestNative继承Library
- 创建一个本地方法(用native修饰的方法)cppHello()
- 创建头文件 library.h,定义一个函数cppHello();
- 创建cpp文件 library.cpp,实现头文件中的cppHello();
- 执行命令生成liblibrary.so动态库
g++ library.cpp -fPIC -shared -o liblibrary.so
- 接口内用Native.load()方法加载函数库(使用绝对路径)创建一个TestNative实例
- TestNative.testNative.cppHello();进行调用
java代码
import com.sun.jna.*;
import java.util.Arrays;
import java.util.List;
/**
* @Author :feiyang
* @Date :Created in 11:14 AM 2019/10/14
*/
public interface TestNative extends Library {
TestNative testNative = Native.load("/Users/liblibrary.so", TestNative.class);
/**
*
* @author feiyang
* @return void
* @date 2019/10/22
* @throws
*/
void cppHello();
/**
* 测试方法
* @param args
*/
static void main(String[] args) {
TestNative.testNative.cppHello();
}
}
c++代码
头文件 library.h
#ifndef UNTITLED1_LIBRARY_H
#define UNTITLED1_LIBRARY_H
#include <iostream>
extern "C" {
using namespace std;
void cppHello();
};
#endif
cpp文件 library.cpp
#include "library.h"
#include <iostream>
extern "C" {
void cppHello() {
using namespace std;
cout << "cpp执行:cppHello!" << endl;
};
};
2、基本传参
实现步骤