java - JNA Structure.getFieldOrder() 与声明的字段名称不匹配
问题描述
我有以下异常在 Structure 中定义 JNA 结构:
线程“main”java.lang.Error 中的异常:com.MyInterface$mine$ByReference 类上的 Structure.getFieldOrder() 返回与声明的字段名称不匹配的名称 ([color, data, hello, rice, str, wild])
查看我的 Cpp 结构:
typedef struct s_mine
{
e_color color; //e_color is enum type made of int values
his data;
int str;
unsigned int wild;
unsigned int hello;
float rice;
} mine;
typedef struct s_his
{
unsigned char * data;
unsigned int size;
} his;
请参阅下面的示例,即 MyInterface.java:
public interface MyInterface extends Library {
public static class his extends Structure {
public static class ByReference extends his implements Structure.ByReference {} // Need the stucture address as it a parameter of a particular wrapped method
public static class ByValue extends his implements Structure.ByValue {} // Need the structure value inside "mine" Structure
public Pointer data;
public int size;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "data", "size"});
}
}
public class mine extends Structure {
public static class ByReference extends mine implements Structure.ByReference {}
int color;
his.ByValue data;
int str;
int wild;
int hello;
float rice;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] {"color","data","str","wild","hello","rice"});
}
}
}
使用 MyInterface 的主类包含以下行,我对“我的”结构字段的顺序有例外:
final MyInterface.mine.ByReference mine_ref = new MyInterface.mine.ByReference();
因此,我调试代码以便在 Structure.class 之后进入 JNA 进入以下 getFields 方法(其中我得到异常(下面的第二个):
protected List<Field> getFields(boolean force) {
List<Field> flist = getFieldList();
Set<String> names = new HashSet<String>();
for (Field f : flist) {
names.add(f.getName());
}
List<String> fieldOrder = fieldOrder();
if (fieldOrder.size() != flist.size() && flist.size() > 1) {
if (force) {
throw new Error("Structure.getFieldOrder() on " + getClass()
+ (fieldOrder.size() < flist.size()
? " does not provide enough"
: " provides too many")
+ " names [" + fieldOrder.size()
+ "] ("
+ sort(fieldOrder)
+ ") to match declared fields [" + flist.size()
+ "] ("
+ sort(names)
+ ")");
}
return null;
}
Set<String> orderedNames = new HashSet<String>(fieldOrder);
if (!orderedNames.equals(names)) {
throw new Error("Structure.getFieldOrder() on " + getClass()
+ " returns names ("
+ sort(fieldOrder)
+ ") which do not match declared field names ("
+ sort(names) + ")");
}
sortFields(flist, fieldOrder);
return flist;
}
这就是我探索以下字段值的原因,因为在 getFields 方法中引发了异常
fieldOrder = [color, data, str, wild, hello, rice]
orderedNames = [str, color, data, hello, rice, wild]
引发异常是因为名称为空。无论如何,由于 HashSet java.util 类不能保证顺序会随着时间的推移保持不变,我肯定认为 JNA Structure.java 中存在错误。因为我的 fieldOrder 的顺序是按new HashSet<String>(fieldOrder)
指令以随机顺序排序的,因此与orderedNames 的顺序不同。
有没有人同意我的观点,或者我错过了关于声明和使用我的 JNA 结构的方式的一些内容?
如果没有错误(即故意使用 HashSet ......)我在声明我的结构时是否做错了什么?我该如何解决这个问题?
解决方案
您的错误在mine
结构中:您需要将字段声明为public
. JNA 使用反射并依赖public
修饰符来映射要映射到本机的字段;否则它们只是被认为是类中的辅助字段。
否则,映射将按照您的方式工作,但请考虑以下改进:
ByValue
当用作嵌套结构时,您不需要使用结构的版本。这是默认设置。唯一需要对嵌套结构采取特殊操作的情况是,如果它是ByReference
.- 同样,
ByReference
用作函数参数时是默认值。只有当函数需要一个ByValue
参数时,它才需要特殊处理。
- 同样,
- 在 JNA 5.x中,override 的使用被注释
getFieldOrder()
替换了。@FieldOrder
虽然您所拥有的工作有效,但如果您只是将该注释放在结构之前,您的代码将更具可读性,例如,
@FieldOrder({"data", "size"})
class his extends Structure {
// etc...
}
- 接口变量/类/等。默认情况下是
public
,static
,final
因此使用这些修饰符是多余的。
推荐阅读
- python - 将数据导入 csv 文件以获取 matplotlib 图形的问题
- javascript - 使用相同的JS函数按类显示和隐藏不同的元素
- apache - mod_rewrite 删除域名的最后一部分,同时保留 URL 的其余部分
- python - 清除命令不断受到速率限制
- rss - 获取 Bittube.tv 个人资料的 RSS 提要?
- python - 如何使用 python requests get 获取重定向 URL
- reactjs - react-mentions debounce 输入文本
- javascript - 实现加载屏幕反应
- go - 使用 go 语言选择查询 - MYSQL
- c# - Identity Server 4 和 ASP.NET Web 窗体客户端 - 无效的授权类型