Reputation: 125
I have a C function, which creates an array of structs
int createArray(myStruct** data_array);
From C I call the function like this:
myStruct* data_array;
int size = createArray(&data_array);
I want to call createArray
in a similar way with JNA. I've generated the wrapper using JNAerator.
int createArray(myStruct.ByReference[] data_array);
I don't know what to pass to the JNA method createArray
since data_array
is actually a output parameter. I actually think the generated JNA method is wrong since I don't want to pass an array of myStruct
, I want to receive one.
Shouldn't the parameter of the JNA method be PointerByReference
?
Here are some tries that didn't worked for me
PointerByReference ptr = new PointerByReference();
int size = api.createArray(ptr); //Invalid memory access
myStruct.ByReference[] array = new myStruct.ByReference[10];
Arrays.fill(stLinks, new myStruct.ByReference()); //without this I get NullpointerException
int size = api.createArray(array); //Invalid memory access
Upvotes: 1
Views: 359
Reputation: 9091
Shouldn't the parameter of the JNA method be
PointerByReference
?
Debugging this requires figuring out what exactly the native method does, which is likely documented in the API and not obvious from the method signatures.
PointerByReference
allocates a pointer-sized block of memory on the Java side, and is generally the correct thing to pass when native is filling it with a value. After your clarification/answer it appears your invalid memory access was external to this code.
Your attempt to allocate an array of structures doesn't work because they require contiguous memory, which you need to allocate using toArray()
if you're responsible for the allocation -- but it looks like you're not!
So you can pass a PointerByReference
and extract its pointed-to (Pointer
) value using getValue()
. You could then use that pointer in a Structure
constructor to populate the Java-side structure (array).
PointerByReference pbr = new PointerByReference();
int size = api.createArray(pbr);
MyStruct[] foo = (MyStruct[]) new MyStruct(pbr.getValue()).toArray(size);
// you may need to `read()` indices past 0 from this array
Upvotes: 1
Reputation: 125
Seems like the problem with Invalid memory access was caused by other side effects. I had to call other functions from the API before I can use createArray.
The working code is now:
PointerByReference ptr = new PointerByReference();
int size = api.createArray(ptr);
Pointer ptrToFirst = ptr.getValue();
myStruct firstElement = new myStruct(ptrToFirst);
myStruct[] array = (myStruct []) firstElement.toArray(size);
//Work with Array
api.deleteArray();
Upvotes: 1