Java – How to use JNA to pass com.sun.jna.Structure from Java to structures in C

How to use JNA to pass com.sun.jna.Structure from Java to structures in C… here is a solution to the problem.

How to use JNA to pass com.sun.jna.Structure from Java to structures in C

I’m leaving how this is delivered examples of com.sun.jna.structure contain com.sun.jna.StringArray uses JNA to convert from Java to native C code and cannot be converted in C The structure content is successfully obtained in the code.

Note that I can successfully pass a structure in C code to a structure in Java

, but I can’t create a structure in Java code and send it successfully to C code as a structure.

Here 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);

It looks simple, but it doesn’t work.

Successfully enters C code as expected, but the pointer in the structure is empty and the length is zero.

This is the StringList structure in 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(); }
}

The corresponding struct in C code is as follows:

typedef struct string_list {
    uint64_t length;
    const char **strings;
} string_list;

The following is the method definition in C code:

const char* my_method(struct string_list *members)
{
   //.................
}

Use ndk-gdb, and go into this function, which 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 looks like it should work, so why isn’t its value written into the C code? What am I missing?

Also note that if the StringArray is not in the structure, I can send it from Java code directly to C code:

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)
{
    //......
}

In this case, JNA seems to work as expected. So why doesn’t it work with the structure as the documentation states it should?

Solution

Do not mark fields as mutable. When you do this, JNA does not write to them unless you execute explicit Structure.writeField().

Related Problems and Solutions