I'm a complete beginner at JNA
I am passing an empty structure to the function, which consists of structures nested in it. After calling the function, I expect the fields to be filled in, but the internal structure is always null
The native method looks like this:
SDK_API int LoadFile (char *fname, struct MyLoadFile *logfile, int reset);
The structure looks like this:
struct MyLoadFile {
struct Src *src
};
struct Src {
char *FileId;
unsigned long Version[4];
struct Msg *Messages;
struct Src *next;
};
My JNA function looks like this:
int LoadFile(ByteBuffer fname, MyLoadFile logfile, int reset);
I tried calling the function:
MyLoadFile file = new MyLoadFile ();
byte[] bytes = "D:/test/file".getBytes(StandardCharsets.US_ASCII);//Windows OS
ByteBuffer fName = ByteBuffer.allocateDirect(bytes.length);
fName.put(bytes);
fName.flip();
System.out.println("Ret code: " + MyLibrary.LoadFile(fName, file, 0));
**//file.src == null**
From the c++ code, I call the method as follows (and it works):
struct MyLoadFile logfile;
LoadFile ("D:/test/file", &logfile, true)
The structure classes are generated by JNAerator and look like this:
public class MyLoadFile extends Structure {
public Src.ByReference src;
public MyLoadFile() {
super();
}
protected List<String > getFieldOrder() {
return Arrays.asList("src");
}
public MyLoadFile(Src.ByReference src) {
super();
this.src= src;
}
public MyLoadFile(Pointer peer) {
super(peer);
read();
}
public static class ByReference extends MyLoadFile implements Structure.ByReference {}
public static class ByValue extends MyLoadFile implements Structure.ByValue { }
}
public class Src extends Structure {
public Pointer FileId;
public NativeLong[] Version = new NativeLong[4];
public Msg.ByReference Messages;
public ByReference next;
public Src() {
super();
}
protected List<String > getFieldOrder() {
return Arrays.asList("FileId", "Version", "Messages", "next");
}
public Src(Pointer FileId, NativeLong Version[], Msg.ByReference Messages,
ByReference next) {
super();
this.FileId = FileId;
if ((Version.length != this.Version.length))
throw new IllegalArgumentException("Wrong array size !");
this.Version = Version;
this.Messages = Messages;
this.next = next;
}
public Src(Pointer peer) {
super(peer);
read();
}
public static class ByReference extends Src implements Structure.ByReference {}
public static class ByValue extends Src implements Structure.ByValue {}
}
JNA does not automatically read the values at Structure.ByReference
pointers, as there is a possibility that they may be null.
You may be able to solve the problem by explicitly reading your MyLoadFile
structure after your method call.
MyLibrary.LoadFile(fName, file, 0);
file.read();
// file.src should now be populated
Another solution here is to map src
as a Pointer
:
@FieldOrder ({ "src" })
public class MyLoadFile extends Structure {
public Pointer src;
}
Then after calling LoadFile()
use that pointer to instantiate the nested structure with its constructor taking a pointer argument:
MyLibrary.LoadFile(fName, file, 0);
Src src = new Src(file.src);
You may need to do something similar to access the nested Msg.ByReference
structure.