java调用动态库dll/so(二)jna结构体Structure介绍和使用
目录
前言
JNA数据类型与java数据类型映射关系
JNA指针介绍
怎样构建java结构体
更简单的构造结构体
C/C++里有结构体struct,甚至C#中也具有,然而java中却不具有结构体,当调用动态库.so和.dll时,函数接口上很多数据都是结构体,这该怎么办呢,放心jna为我们提供了Structure这个类,只要继承该类,就可实现java结构体。我们从以下几点来进行介绍。
在jna中数据类型的对应关系使用的是TypeMapper这个接口来定义jna自定义数据类型与java类型的转换。官方jna数据类型与java数据类型映射关系如下:
以下为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类的实例。
- 继承Structure,并在结构体上使用FieldOrder注解;
- 继承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.dllSolibLoad.lib.model.struct;
import java.lang.reflect.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 {
}
@Override
protected List<String> getFieldOrder() {
return getStructFields();
}
/**
* 自定义反射获取字段顺序
*
* @return
*/
private List<String> getStructFields() {
List<String> feilds = new LinkedList<>();
Field[] declearedFeilds = this.getClass().getDeclaredFields();
if (declearedFeilds != null && declearedFeilds.length > 0) {
for (Field f : declearedFeilds) {
feilds.add(f.getName());
}
}
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.println(feidlSb.toString());
}
}
}
继承类举例:
package maoko.dllSolibLoad.lib.model.struct.meta;
import com.sun.jna.NativeLong;
import maoko.dllSolibLoad.lib.model.struct.JavaStructBase;
/**
* 时间信息
*
* @author fanpei
*
*/
public class StruFileTime extends JavaStructBase {
public NativeLong dwLowDateTime;// 开始时间
public NativeLong dwHighDateTime;// 结束时间
}
从以上代码中可以看出JavaStructBase的getStructFields()方法实现了重载,利用反射获取子类申明的属性字段返回字段顺序list,子类则只需定义属性字段即可,且子类具有ByValue和ByReference两个静态类。
代码完整地址:https://download.csdn.net/download/fanpei_moukoy/11195072
[https://github.com/maokofan/maoko.dllSoLibLoad][https_github.com_maokofan_maoko.dllSoLibLoad]
还没有评论,来说两句吧...