I have the following function in C:
EXPORT int GetInfo(MyObject* &myObjects);
typedef struct MyObject
{
char info1[1025];
unsigned long sizeF;
char info2[20];
};
Then I invoke:
MyObject* list1;
int count = GetInfo(list1);
and iterate list1 in order to get information from each MyObject object (count -> number of elements in list1).
Now, I'm trying to make the counterpart in JNA. Thus, I have:
int GetInfo(PointerByReference myObjets);
public class MyObject extends Structure {
public static class ByReference extends MyObject implements Structure.ByReference {
}
public String info1;
public NativeLong sizeF;
public String info2;
public MyObject() {
}
public MyObject(Pointer pointer) {
super(pointer);
}
@Override
protected List getFieldOrder() {
return Arrays.asList(new String[]{"info1", "sizeF", "info2"});
}
}
Then:
PointerByReference ptrRef = new PointerByReference();
int count = myLib.GetInfo(ptrRef);
if (count > 0) {
Pointer pointer = ptrRef.getValue();
MyObject myObject = new MyObject(pointer);
MyObject[] myObjects = (MyObject[]) myObject.toArray(count);
}
Unfortunately, all fields in myObjects have default values (null/0). I also tried:
int GetInfo(MyObject.ByReference myObjets);
MyObject.ByReference byRef = new PointerByReference();
int count = myLib.GetInfo(byRef);
if (count > 0) {
MyObject[] myObjects = (MyObject[]) byRef.toArray(count);
}
In this case, only the first field in first element of myObjects array was filled. The rest had default values.
What should I do in order to get an array of MyObjects with filled all fields.
Some time ago I found the solution. I don't know if it is wise, but it worked for me. So if someone will have a similar problem, then here you go:
In MyObject class I added 2 methods:
static MyObject[] fromArrayPointer(Pointer pointer, int numberResults) {
MyObject[] arr = new MyObject[numberResults];
int offset = 0;
for (int i = 0; i < numberResults; i++) {
arr[i] = fromPointer(pointer, offset);
offset += <size of structure>;
}
return arr;
}
static MyObject fromPointer(Pointer pointer, int offset) {
MyObject inst = new MyObject();
inst.info1= pointer.getString(offset);
offset += 1025;
inst.sizeF = pointer.getNativeLong(offset);
offset += 4; // long but 4 bytes because of machine
inst.info2 = pointer.getString(offset);
offset += 20;
return inst;
}
Honestly, you have to experiment with those numbers and size of structure. Remember about data aligment problem here.
Then, you have:
if (count > 0) {
MyObject[] myObjects = MyObject.fromArrayPointer(ptrRef.getValue(), count);
}