JNA简单使用
近期使用Java开发有关于摄像机接收到数据的上传,因为摄像机处理图像是用C语言实现的,所以开发需要用到JNA,实现JAVA对C语言的回调,因为具体的开发方式官方文档里面有示例,所以本文只是简单的把需要注意的点罗列出来。
一、 定义
JNA提供一些JAVA工具类,在运行期间访问本地库,如dll/so。
二、 数据类型对照表
官方提供的数据参考表完全够用,当使用数据参考时候,注意参考头文件宏定义。
1、常见数据类型对照
Java 类型 | C 类型 | 原生表现 |
---|---|---|
boolean | int | 32位整数 (可定制) |
byte | char | 8位整数 |
char | wchar_t | 平台依赖 |
short | short | 16位整数 |
int | int | 32位整数 |
long | long long, __int64 | 64位整数 |
float | float | 32位浮点数 |
double | double | 64位浮点数 |
Buffer/ [Pointer] | pointer | 平台依赖(32或 64位指针) |
Pointer/array | 32或 64位指针(参数/返回值) |
其他常用:
Java 类型 | C 类型 | 原生表现 |
---|---|---|
String | char* | /0结束的数组 (native encoding or jna.encoding) |
WString | wchar_t* | /0结束的数组(unicode) |
String[] | char** | /0结束的数组的数组 |
WString[] | wchar_t** | /0结束的宽字符数组的数组 |
Structure[] | struct[] | 结构体的数组,邻接内存 |
Callback | Java函数指针或原生函数指针 | |
NativeMapped | varies | 依赖于定义 |
NativeLong | long | 平台依赖(32或64位整数) |
PointerType | pointer | 和 Pointer相同 |
Structure | struct*\ struct | 指向结构体的指针或结构体,都明确指出,后面详细讨论 |
2、C语言部分常用定义,注意dll内的定义。
#define WORD unsigned short
#define DWORD unsigned int
#define LONG int
#define LLONG long
#define INT64 long long
#define LDWORD long
#define BOOL int
三、调用方法
1、简单函数调用
这里使用deSDK.dll,放到工程目录之下。
-
dll提供接口函数:
BOOL C_Init(LDWORD dwUser);
-
Java代码声明:
public class getdeSDK{ public interface Function extends Library { Function Jinit = (Function)Native.loadLibrary("getdeSDK.dll",Function.class); public boolean C_Init(Nativelong dwUser); } }
-
Java代码调用:
boolean flag = getSDK.Function.Jinit.C_Init(1);
2、回调函数调用
在dll中定义回调函数,使用时候直接继承(implements)java中声明的接口。
-
Java代码声明
public interface fDataCallBack extends StdCallCallback { public int invoke(NativeLong dwUser); }
3、模拟结构体
回调函数参数会出现结构体或者以结构体本身作为其他的结构体的元素存在,判断结构体是以本身传递还是所为指针存在,详细使用看官方文档。
-
java声明
public static class MYCLASS extends Structure{ //这里写与dll中相对应的变量与常量。 public Nativelong dwUser; public byte[] dwName;//char数组 }
4、注意事项
-
枚举(enum)
在dll中使用enum,在java声明中同样使用enum,但要注意的是,在C中直接使用枚举成员可以作为序号来用,而java需要在枚举成员后加ordinal()方法。 -
ByReference与ByValue
public static class ByValue extends MYCLASS implements Structure.ByValue {} public static class ByReference extends MYCLASS implements Structure.ByReference {}
如果你的Struct实现Structure.ByReference接口,那么JNA认为你的Struct是一个指针。指向C语言的结构体。
如果你的Struct实现Structure.ByValue接口,那么JNA认为你的Struct是值类型,就是C语言的结构体
四、参考资料
1、官方文档:
- JNA使用入门
- 接口描述
- java接口到本地接口的映射
- 使用指针和数组
- 使用结构体和联合
- 使用引用参数
- 定制化类型映射
- 回调、函数指针、闭包
- 动态类型语言支持(JRuby、Jython)
- 平台库
- 直接方法调用(优化)
- 常见问题列表
- 使用注意要点
2、部分博客: