当前位置:文档之家› JNA学习笔记

JNA学习笔记

JNA学习笔记
JNA是什么:
JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。

开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。

JNA优点:
JNA可以让你像调用一般java方法一样直接调用本地方法。

就和直接执行本地方法差不多,而且调用本地方法还不用额外的其他处理或者配置什么的,也不需要多余的引用或者编码,使用很方便。

JNA使用:
1)POM
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
在POM文件中加入上述dependency
2)准备一个dll文件
示例文件(仅核心代码):
的相关使用部分。

将编译得到的dll文件(这里是”JNATestDll.dll”)放在java工程的根目录下(根据需要,可以自行调整)
3)编写Java代码
2.接口继承自com.sun.jna.Library。

3.接口内部需要定义一个公共静态常量(这里是instanceDll),通过它调用dll的相关函数。

3-2)带有基本变量参数的接口调用
JNA提供了Java和C数据类型的映射
3-3)简单指针和引用(不需要Java分配空间,非自定义结构体,不含多级指针)
2. 一级指针和引用都使用ByReference作为参数3-4)简单数组(内部类型数组)
3-5)自定义简单结构体
调用部分
2. 结构体中公共参数的顺序、类型必须一致
3-6)结构体内嵌套数组(使用网上示例,不包含指针)
Tips 1.结构体必须在内部进行数组定义
C语言的结构体是一段连续的内存,内存的大小是编译时确定的。

因此,数组必须定义。

否则编译不会成功。

对应的Java类中,我们也应该在类定义时为数组定义。

尽管实际上在使用时再赋值也可以。

但是,强烈不建议你这样做。

如,上面
public UserStruct.ByValue[] users=new UserStruct.ByValue[100];
定义100个元素的数组,如果你不再类内部定义。

而在使用时定义,如果你没有正确赋值,没有定义为100个元素,就会出错。

从表面上看,CompanyStruct类占用的内存是:
NativeLong id
WString name;
public UserStruct.ByValue[] users=new UserStruct.ByValue[100];
public int count;
这4个元素占用的内存的总和。

由于Java的数组是一个对象,users中实际保存的也应该是一个引用,也就是指针,32bit。

那么CompanyStruct类占用的内存就比对应的C结构体:
struct CompanyStruct{
long id;
wchar_t* name;
UserStruct users[100];
int count;
};
小很多。

内存少用很多。

3-5)的Tips中提到过:

3-7)传入多级指针,及为调用接口创建空间
调用部分
public class mainFrame {
public static void main(String[] args) {
int size = 4;
Pointer p = new Memory(size * Pointer.SIZE);
Pointer[] pp = new Pointer[size];
for(int i=0;i<size;++i) {
pp[i] = new Memory(size * Native.getNativeSize(Integer.TYPE));
p.setPointer(i*Pointer.SIZE, pp[i]);
}
PointerByReference n = new PointerByReference(p);
JNATestDll.instanceDll.rrreference(n, size);
for (int i=0; i<size; ++i) {
for (int j=0; j<size; ++j) {
System.out.println("rrreference: n[" + i + "][" + j + "]=" +
p.getPointer(i*Pointer.SIZE).getInt(j*Native.getNativeSize(Integer.TYPE)));
}
}
}
}
Tips 1.不论dll接口接收几级指针,只需要传PointerByReference(指针的指针)作为参数。

2.需要预先为指针创建内存时,使用com.sun.jna.Memory。

创建时注意指定的大小(type的size*数量)。

相关主题