I've used the pattern below before, as I found the performance higher than the automatic marshaling performed by JNA. Give it a shot.
First, the structure:
public class Code {
private Pointer pointer;
Code() {
long memory = Native.malloc(6);
pointer = new Pointer(memory);
}
void free() {
Native.free(Pointer.nativeValue(pointer));
}
Pointer getPointer() {
return pointer;
}
byte getA() {
return pointer.getByte(0);
}
byte getB() {
return pointer.getByte(1);
}
byte getC() {
return pointer.getByte(2);
}
...
void setA(byte a) {
pointer.setByte(0, a);
}
void setB(byte b) {
pointer.setByte(1, b);
}
void setC(byte c) {
pointer.setByte(2, c);
}
...
}
Next, the API:
class JNATest {
static {
Native.register("StructTest"); // undecorated name ... becomes libStructTest.so on Linux
}
public static native void printStruct(Pointer obis);
}
Finally, the usage:
Code code = new Code();
code.setA((byte) 'a');
code.setB((byte) 'b');
...
JNATest.printStruct(code.getPointer());
code.free(); // free the memory allocated in the constructor
If you have different structures, with short
, int
, long
, etc. the Pointer
class provides easy accessors for reading/writing them.