java调⽤动态库dllso(⼆)jna结构体Structure介绍和使⽤⽬录
前⾔
C/C++⾥有结构体struct,甚⾄C#中也具有,然⽽java中却不具有结构体,当调⽤动态库.so和.dll时,函数接⼝上很多数据都是结构体,这该怎么办呢,放⼼jna为我们提供了Structure这个类,只要继承该类,就可实现java结构体。我们从以下⼏点来进⾏介绍。
JNA数据类型与java数据类型映射关系
在jna中数据类型的对应关系使⽤的是TypeMapper这个接⼝来定义jna⾃定义数据类型与java类型的转换。官⽅jna数据类型与java数据类型映射关系如下:
JNA指针介绍
以下为Structure的部分源码,其中包含两个接⼝,ByValue和ByReference。
ByReference具有很多实现,例如:
ByteByReference
DoubleByReference
FloatByReference
IntByReference
LongByReference
NativeLongByReference
PointerByReference
ShortByReference
W32API.HANDLEByReference
X11.AtomByReference
X11.WindowByReference
ByValue                    :  结构体⾃⾝实例对象
ByReference            :指针
PointerByReference  :指向指针的指针
在JNA中模拟指针,最常⽤到的就是Pointer类和PointerByReference类。Pointer类代表指向任何东西的指针,PointerByReference类表⽰指向指针的指针。Pointer类更加通⽤,事实上PointerByReference类内部也持有Pointer类的实例。
怎样构建java结构体
1. 继承Structure,并在结构体上使⽤FieldOrder注解;
2. 继承Structure,重载getFieldOrder函数。
第⼀种为官⽅使⽤⽅法,第⼆个⽅法为我⾃定义,⼆者⽐较,第⼀种使⽤复杂,需要在类上使⽤注解并设置value;第⼆种⽅法则简单,接
下来我们详细描述这两种⽅法。
package maoko.dllSolibLoad;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
@FieldOrder("a,b")
public class TestStructure_WithFieldOrder extends Structure {
public int a;
public int b;
}
FieldOrder⾥的顺序为⾃⼰定义结构体顺序。
以下为第⼆种,重载:
package maoko.dllSolibLoad;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Structure;
public class TestStructure_WithOverride extends Structure {
public int a;
public int b;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("a", "b");
}
}
更简单的构造结构体
由第⼆种⽅式进⾏衍⽣,使⽤java反射技术将此⽅式变的更加的简单,具体⽅式为:使⽤⼀个⾃定义基本类即可,⼦类只需要定义⾃⼰的属性字段,基类定义如下:
package maoko.del.struct;
import flect.Field;
import java.util.LinkedList;
import java.util.List;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
/**
* java struct base
*
* @author fanpei
*
*/
public abstract class JavaStructBase extends Structure {
/**
* 默认构造函数
*/
public JavaStructBase() {
}
/**
* 构造函数
*
* @param _pointer
*/
public JavaStructBase(Pointer _pointer) {
super(_pointer);
}
/**
* 结构体的引⽤
*
* @author maoko
*
*/
public static class ByReference extends JavaStructBase implements Structure.ByReference { }
/**
* 结构体对象
*
* @author fanpei
*
*/
public static class ByValue extends JavaStructBase implements Structure.ByValue {
}
@Overridejava jna
protected List<String> getFieldOrder() {
return getStructFields();
}
/**
* ⾃定义反射获取字段顺序
*
* @return
*/
private List<String> getStructFields() {
List<String> feilds = new LinkedList<>();
Field[] declearedFeilds = Class().getDeclaredFields();
if (declearedFeilds != null && declearedFeilds.length > 0) {
for (Field f : declearedFeilds) {
feilds.Name());
}
}
return feilds;
}
/**
* 打印字段-测试⽤
*/
@Deprecated
public void printStructFeilds() {
List<String> feilds = getStructFields();
if (feilds == null || feilds.size() == 0)
System.out.println("feilds:none");
else {
StringBuilder feidlSb = new StringBuilder("feilds:");
for (String f : feilds) {
feidlSb.append(f);
feidlSb.append(",");
}
System.out.String());
}
}
}
继承类举例:
package maoko.a;
import com.sun.jna.NativeLong;
import maoko.del.struct.JavaStructBase;
/**
* 时间信息
*
* @author fanpei
*
*/
public class StruFileTime extends JavaStructBase {
public NativeLong dwLowDateTime;// 开始时间
public NativeLong dwHighDateTime;// 结束时间
}
从以上代码中可以看出JavaStructBase的getStructFields()⽅法实现了重载,利⽤反射获取⼦类申明的属性字段返回字段顺序list,⼦类则只需定义属性字段即可,且⼦类具有ByValue和ByReference两个静态类。
代码完整地址:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。