Hi all,
please tell me if the following is a legitimate bug or if I'm using JNA in unfortunate ways.
I'd like to use a struct and that struct should have a member of type NativeMapped on the Java side.
This is my reproducer within the JNA test suite, as patch:
diff --git a/native/testlib.c b/native/testlib.c
index 5ea8b605b..a775d1e35 100644
--- a/native/testlib.c
+++ b/native/testlib.c
@@ -112,7 +112,14 @@ struct CheckFieldAlignment {
float floatField;
double doubleField;
};
+
+struct MyStruct {
+ char *myString;
+};
+EXPORT void acceptMyStruct(struct MyStruct *it) {
+ printf("%s", it->myString);
+}
static int _callCount;
EXPORT int
diff --git a/test/com/sun/jna/ReturnTypesTest.java b/test/com/sun/jna/ReturnTypesTest.java
index d7b340cde..08c9105e9 100644
--- a/test/com/sun/jna/ReturnTypesTest.java
+++ b/test/com/sun/jna/ReturnTypesTest.java
@@ -130,6 +130,7 @@ public class ReturnTypesTest extends TestCase {
Pointer[] returnPointerArgument(Pointer[] arg);
String[] returnPointerArgument(String[] arg);
WString[] returnPointerArgument(WString[] arg);
+ void acceptMyStruct(MyStruct ms);
}
TestLibrary lib;
@@ -225,6 +226,31 @@ public class ReturnTypesTest extends TestCase {
setValue(value);
}
}
+ public static class MyStruct extends Structure {
+ public MyString myString;
+ }
+ public static class MyString implements NativeMapped {
+
+ @Override
+ public Object fromNative(Object nativeValue, FromNativeContext context) {
+ return new MyString();
+ }
+
+ @Override
+ public Object toNative() {
+ return new byte[] { (byte) 0xDEAD, (byte) 0xBEEF };
+ }
+
+ @Override
+ public Class<?> nativeType() {
+ return byte[].class;
+ }
+
+ }
+ public void testInvokeNativeMappedBytes() {
+ lib.acceptMyStruct(new MyStruct());
+ }
+
public static class Custom implements NativeMapped {
private int value;
public Custom() { }
But then I get:
[junit] Testcase: testInvokeNativeMappedBytes(com.sun.jna.ReturnTypesTest): Caused an ERROR
[junit] Invalid Structure field in class com.sun.jna.ReturnTypesTest$MyStruct, field name 'myString' (class com.sun.jna.ReturnTypesTest$MyString): The type "com.sun.jna.ReturnTypesTest$MyString" is not supported: Native size for type "[B" is unknown
[junit] java.lang.IllegalArgumentException: Invalid Structure field in class com.sun.jna.ReturnTypesTest$MyStruct, field name 'myString' (class com.sun.jna.ReturnTypesTest$MyString): The type "com.sun.jna.ReturnTypesTest$MyString" is not supported: Native size for type "[B" is unknown
[junit] at com.sun.jna.Structure.validateField(Structure.java:1246)
[junit] at com.sun.jna.Structure.validateFields(Structure.java:1255)
[junit] at com.sun.jna.Structure.<init>(Structure.java:211)
[junit] at com.sun.jna.Structure.<init>(Structure.java:204)
[junit] at com.sun.jna.Structure.<init>(Structure.java:191)
[junit] at com.sun.jna.Structure.<init>(Structure.java:183)
[junit] at com.sun.jna.ReturnTypesTest$MyStruct.<init>(ReturnTypesTest.java:229)
[junit] at com.sun.jna.ReturnTypesTest.testInvokeNativeMappedBytes(ReturnTypesTest.java:251)
[junit] Caused by: java.lang.IllegalArgumentException: The type "com.sun.jna.ReturnTypesTest$MyString" is not supported: Native size for type "[B" is unknown
[junit] at com.sun.jna.Native.getNativeSize(Native.java:1386)
[junit] at com.sun.jna.Structure.getNativeSize(Structure.java:2284)
[junit] at com.sun.jna.Structure.getNativeSize(Structure.java:2274)
[junit] at com.sun.jna.Structure.validateField(Structure.java:1242)
[junit]
[junit]
[junit] Test com.sun.jna.ReturnTypesTest FAILED
I would assume that JNA can deduce the size if it weren't for NativeMapped. JNA also does it when MyString is not part of a struct, but rather directly used as parameter. Why the difference?
Thanks for reading.