I am starting to use JNA to communicate with a device on the RS485 interface of a computer. Suprisingly to me I came to good results very quickly. But now I am stuck by a simple problem. The library I use accepts a pointer to a pointer of struct. The actual signature is
func(Struct1 **, Struct2 **, Struct3 *, Struct4 *, long)
Now to indicate the size of the first parameter the library expects the last pointer to be a NULL pointer. This is what fails. Following code is what I tried so far:
Struct1.ByReference[] s = (Struct1.ByReference[]) new Struct1.ByReference().toArray(size);
int pos = 0;
// ...
// for loop to set the s[pos] struture values
for(pos = 0; pos < size - 1; pos++)
// ...
// Now set the last array element to a null pointer to indicate end-of-list
s[pos].getPointer().setPointer(0, null);// Following does not work: results in zero memoried structure
s[pos] = null; // Following does not work wither: NullPointerException at com.sun.jna.Structure.autoWrite
EDIT 1
s[pos] = new Struct1.ByReference(Pointer.NULL); // results in zero memoried structure as well
EDIT 2
According to technomage's question. If I were to write C code it would probably look something like that:
Struct1 **s = malloc(n * sizeof(Struct1*));
for(int i=0; i<n; i++)
{
if(i == n -1)
{
s[i] = NULL;
}
else
{
s[i] = malloc(sizeof(Struct1));
s[i].bla = value;
....
}
}
But be warned: I am not very skilled in C/C++. I consider Java to be my domain.
Has anyone had a similar problem? Maybe I am just not seeing the wood for the trees...
Thanks in advance.
Structures in JNA are pointers, so what you really need here is a pointer to a (pointer to a) Structure, which is a PointerByReference
-- in your case, an array of them.
Given the code example above, you'll create your array of Structures, one less than n:
Struct1[] struct1Array = new Struct1[n-1];
This only allocates the Java memory for the array.
Next you'll instantiate and write the changes you make to native memory:
for (int i = 0; i < n-1; i++) {
struct1Array[i] = new Struct1();
struct1Array[i].bla = value;
struct1Array[i].write();
}
The new Struct1()
allocates native side memory for these structures. It's possible to use the Structure.toArray()
method to do this as well; I'm intentionally doing this a bit more manual and low-level to try to make clear what's happening.
Then you'll create a corresponding PointerByReference
array to hold the pointers to these structures. You'll add an extra element for the null:
PointerByReference[] pbrArray = new PointerByReference[n];
Again, this is only java-side allocation. And then you fill it with pointers to the pointers to the structure, obtained from the Structure.getPointer()
method:
for (int i = 0; i < n-1; i++) {
pbrArray[i] = new PointerByReference(struct1Array[i].getPointer());
}
pbrArray[n - 1] = new PointerByReference(Pointer.NULL);
The new PointerByReference()
here allocates the native side memory for the pointer itself, which points to the native-side structure you allocated earlier.
From how I understand your initial question, you will pass this PointerByReference
array to your function, which presumably updates your structures.
Since you created the two arrays in this fashion, you can keep track of their correspondence by array index. You may have to iterate through the structure array and read()
the native memory into the Java-side structure to do further processing with it. Typically when you work directly with Structures being passed to methods they autowrite and autoread, but when using a PointerByReference
to indirectly reference the Structure, JNA isn't as friendly.
As an alternative to tracking the two arrays by corresponding indices, you could "forget" the initial Structure assignment and recover it later using the PointerByReference.getValue()
method on your array to recover a pointer to the memory for the structure, and then instantiate a new structure using that Pointer in its constructor (e.g. new Struct1(pbr.getValue())
which calls super()
with that pointer).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With