jna 构造函数_如何使用TypeConverter通过JNA将C整数映射到Java枚举?

博客介绍了在使用JNA时遇到的问题,即如何通过自定义TypeConverter将C库返回的整数映射到Java的枚举类型。作者详细展示了尝试解决这个问题的过程,包括自定义TypeConverter类和SentinelTypeMapper,并最终解决了加载库时的错误。然而,尽管解决了初始化错误,但返回的枚举值仍然是null,可能是因为JNA在处理枚举类型的映射时存在错误。
摘要由CSDN通过智能技术生成

我想自动进行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对象.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值