概述
我想自动进行JNA的转换.现在我正在遵循第二个答案
in a very similar question和JNA自己的
EnumConverter实用程序类的解决方案.有一个关键的区别,我的枚举有一个构造函数参数.
我定义TypeConverter的代码:
public class SentinelStatusConverter implements TypeConverter {
@Override
public SentinelStatus fromNative(Object nativeValue, FromNativeContext context) {
Integer code = (Integer) nativeValue;
return SentinelStatus.fromCode(code);
}
@Override
public Integer toNative(Object value, ToNativeContext context) {
SentinelStatus status = (SentinelStatus) value;
return Integer.valueOf(status.getCode());
}
@Override
public Class nativeType() {
return Integer.class;
}
}
public class SentinelTypeMapper extends DefaultTypeMapper {
public SentinelTypeMapper() {
addTypeConverter(SentinelStatus.class, new SentinelStatusConverter());
}
}
这里的代码直接注册本机C库以及我的自定义TypeMapper. C函数返回一个int,我想自动映射到SentinelStatus枚举:
public class SentinelLibrary {
static {
Map options = new HashMap();
options.put(Library.OPTION_TYPE_MAPPER, new SentinelTypeMapper());
Native.register(NativeLibrary.getInstance("libnamelib", options));
}
public static native SentinelStatus hasp_get_sessioninfo(
NativeLong sessionHandle,
String query,
PointerByReference info);
}
SentinelStatus是这样的枚举:
public enum SentinelStatus {
HASP_STATUS_OK(0),
HASP_SOME_ERROR(13),
...
HASP_NOT_IMPL(1831);
private final int code;
SentinelStatus(final int code) { this.code = code; }
public int getCode() { return this.code; }
public static SentinelStatus fromCode(final int code) {
for (SentinelStatus status : EnumSet.allOf(SentinelStatus.class)) {
if (code == status.getCode()) {
return status;
}
}
return SentinelStatus.HASP_NOT_IMPL;
}
}
使用此JNA映射和转换器,每当我尝试加载SentinelLibrary类时,我都会收到错误:
java.lang.ExceptionInInitializerError
...
Caused by: java.lang.IllegalArgumentException: Unsupported Structure field type class package.name.SentinelStatus
at com.sun.jna.Structure$FFIType.get(Structure.java:1851)
at com.sun.jna.Structure$FFIType.get(Structure.java:1806)
at com.sun.jna.Native.register(Native.java:1438)
at com.sun.jna.Native.register(Native.java:1165)
at package.name.SentinelLibrary.(line with Native.register() call)
我已经阅读了文档,对映射的类或类型没有任何限制.只有NativeMapped接口需要实现者提供公共无参数构造函数.
是否可以通过这种方式将C整数映射到枚举?
更新:
在通过JNA代码进一步搜索后,我已将此字段添加到SentinelStatus枚举中:
public final static TypeMapper TYPE_MAPPER = new SentinelTypeMapper();
现在SentinelLibrary加载没有错误.但是所有返回枚举的方法都返回null,并将错误打印到stderr:
JNA: unrecognized return type, size 4
最佳答案 您最有可能在库定义的上下文之外定义结构(这是存储TypeMapper信息的位置).
您可以在Structure类上显式设置类型映射器,也可以在本机库类中定义Structure类.如果没有为Structure明确定义TypeMapper,它将回退到任何周围的Library类提供的选项.
public class MyStructure extends Structure {
public MyStructure() {
setTypeMapper(new MyTypeMapper());
}
}
或者,
public interface MyLibrary extends Library {
public class MyStructure extends Structure {
}
}
或者直接映射:
public class MyLibrary implements Library {
{ Native.register(...); }
public class MyStructure extends Structure { }
}
当Structure类无法找到显式设置的类型映射器时,它会查找类型为Library的封闭类,并尝试查找实例化该类时使用的选项.加载本机库时会缓存这些选项,因此可以使用库子类作为键通过键查找获得这些选项.您需要实现Library接口,以便将直接映射库识别为本机库类.
编辑
这是JNA的类型映射器处理中的错误(参见project issue).这似乎仅限于直接映射库和枚举类型映射.
编辑
这里有几个JNA错误,如果您想尝试它,可以使用fix is available.此问题与直接映射库上的映射器类型隔离,其中原语正在转换为Java对象.
最后
以上就是飞快丝袜为你收集整理的jna 构造函数_如何使用TypeConverter通过JNA将C整数映射到Java枚举?的全部内容,希望文章能够帮你解决jna 构造函数_如何使用TypeConverter通过JNA将C整数映射到Java枚举?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复