Search code examples
javac++cjava-native-interfacejna

JNA (Java): How to pass an array of pointers to struct?


I'm using JNA to call into a C library from Java.

In my C code I have:

   void printStructArray( SomeStruct **someStruct, int arraySize );

This expects an array of pointers to struct, ie the method does this:

void printStructArray( SomeStruct **someStruct, int arraySize ) {
   for( int i = 0; i < arraySize; i++ ) {
      cout << "someStruct: " << someStruct[i]->aLong << " " << someStruct[i]->aString << " " << someStruct[i]->aDouble << endl;
   }
}

It's just a toy example, but I have an actual library I want to talk to which needs the same type of argument, but I think using a toy example is easier to explain here?

I've tried all sorts of things, but I'm not sure how to (i) declare this function in JNA (ii) call this function in JNA.

My latest (failed) attempt is:

SomeStruct.byReference[] structs = new SomeStruct.byReference[]{
        new SomeStruct.byReference(123,"hey!",1.23),
        new SomeStruct.byReference(456,"cool!",1.45),
        new SomeStruct.byReference(789,"world!",1.67) };
PointerByReference pointerByReference = new PointerByReference(structs[0].getPointer());
JniTest.instance.printStructArray(pointerByReference, 3);

This causes a SIGSEGV.

Alternatively:

SomeStruct.byReference[] structs = (SomeStruct.byReference[]) new SomeStruct().toArray( new SomeStruct.byReference[]{
        new SomeStruct.byReference(123,"hey!",1.23),
        new SomeStruct.byReference(456,"cool!",1.45),
        new SomeStruct.byReference(789,"world!",1.67) } );
PointerByReference pointerByReference = new PointerByReference(structs[0].getPointer());
JniTest.instance.printStructArray(pointerByReference, 3);

This causes an ArrayStoreException

Tried this also:

SomeStruct.byReference[] structs = new SomeStruct.byReference[]{
    new SomeStruct.byReference(123,"hey!",1.23),
    new SomeStruct.byReference(456,"cool!",1.45),
    new SomeStruct.byReference(789,"world!",1.67) };    JniTest.instance.printStructArray(structs, 3);

With method declared as:

void printStructArray(SomeStruct.byReference[] someStructarray, int num);

This gives '0' as the output from the function, although the good point is it doesn't crash, but it's not giving correct behavior either.

Thoughts?


Solution

  • In the end, I never found a working solution to this. What I did was workaround by writing a wrapper interface, in C, which presented a very simple interface to Java, which was then very easy to link to using JNA, without needing Pointer and so on. This worked quite well, and was less effort than trying to get Pointer working.

    So, my interface looked something like:

    int createHandle()
    void doSomething( int handle )
    void releaseHandle( int handle)
    

    It seemed to take a lot less effort to get this working, in terms of time, than trying to create some super complicated jna implementation to directly connect to the underlying c interface.

    The other advantage is this meant it was easy to connect to a c++ library, since this way, the c++ interface is wrapped by a c interface, which is easy to connect to.