How to map C integer to Java enumeration through JNA using TypeConverter?

I would like the conversion done by JNA to be automatic. Right now I am following the solution from the second answer in a very similar question and the JNA own EnumConverter utility class. There is one important difference, my listing has a constructor argument.

My code defining 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<Integer> nativeType() {
        return Integer.class;
    }
}

public class SentinelTypeMapper extends DefaultTypeMapper {
    public SentinelTypeMapper() {
        addTypeConverter(SentinelStatus.class, new SentinelStatusConverter());
    }
}

Here the code directly registers its own C library along with my custom one TypeMapper. The C functions return intwhich I want to automatically map to an enumeration SentinelStatus:

public class SentinelLibrary {
    static {
        Map<String, Object> options = new HashMap<String, Object>();
        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);
}

SentinelStatusis enumas follows:

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.<clinit>(line with Native.register() call)

. NativeMapped , .

C ?

UPDATE: JNA SentinelStatus enum:

public final static TypeMapper TYPE_MAPPER = new SentinelTypeMapper();

SentinelLibrary . , , null , stderr:

JNA: unrecognized return type, size 4
+4
1

, Structure ( TypeMapper).

mapper Structure Structure Library. <<20 > 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 mapper, Library , . , Library . Library, .

JNA (. ). , -, enum.

JNA, , . , mappers , Java.

+2

All Articles