I'm going off of this example of how to pass a com.sun.jna.Structure containing a com.sun.jna.StringArray from Java into native C code using JNA, and having trouble obtaining the Structure contents successfully in the C code.
Note that I can pass a struct from the C code to a Structure in Java successfully, but I'm having trouble creating a Structure in the Java code and successfully sending it to the C code as a struct.
This is the code in question:
String[] user_name_array = new String[3];
user_name_array[0] = "test_user_1";
user_name_array[1] = "test_user_2";
user_name_array[2] = "test_user_3";
StringList.ByReference members = new StringList.ByReference();
members.length = 3;
members.strings = new StringArray(user_name_array);
MyNativeLibrary.myMethod(members);
Seems simple enough, but it's not working.
It gets into the C code successfully as expected, but the Pointer in the Structure is empty, and the length is zero.
Here is the StringList Structure in the Java:
public static class StringList extends Structure {
public volatile long length;
public volatile Pointer strings;
public static class ByValue extends StringList implements Structure.ByValue {}
public static class ByReference extends StringList implements Structure.ByReference {
public ByReference() { }
public ByReference(Pointer p) { super(p); read(); }
}
public StringList() { }
public StringList(Pointer p) { super(p); read(); }
}
Here is the corresponding struct in the C code:
typedef struct string_list {
uint64_t length;
const char **strings;
} string_list;
And here is the method definition in the C code:
const char* my_method(struct string_list *members)
{
//.................
}
Using ndk-gdb, and breaking into this function, this is what it shows:
(gdb) break my_method
(gdb) cont
Continuing.
Breakpoint 1, my_method (members=0x9bee77b0) at ../app/my_code_file.c:368
(gdb) p *members
$1 = {length = 0, strings = 0x0}
It seems like it should work, so why aren't the values making it into the C code? What am I missing?
Also note that I can successfully send a StringArray directly to the C code from the Java code if it's not inside a Structure:
Java:
//This works!
StringList members = MyNativeLib.myTestFunction(3, new StringArray(user_name_array));
C:
//This works!
string_list* my_test_function(uint64_t length, const char **strings)
{
//......
}
It seems that in this case, JNA works as expected. So, why doesn't it work with a Structure as the documentation states it should?
Don't mark the fields as volatile. When you do that, JNA won't write to them unless you do an explicit Structure.writeField().