the struct in my native code:
struct s_xl_daio_data { /* 32 Bytes */
unsigned short flags; // 2
unsigned int timestamp_correction; // 4
unsigned char mask_digital; // 1
unsigned char value_digital; // 1
unsigned char mask_analog; // 1
unsigned char reserved0; // 1
unsigned short value_analog[4]; // 8
unsigned int pwm_frequency; // 4
unsigned short pwm_value; // 2
unsigned int reserved1; // 4
unsigned int reserved2; // 4
};
my Java class:
@FieldOrder ({"flags", "timestamp_correction", "mask_digital",
"value_digital", "mask_analog", "reserved0", "value_analog",
"pwm_frequency", "pwm_value", "reserved1", "reserved2"})
public class s_xl_daio_data extends Structure {
public short flags; // 2
public int timestamp_correction; // 4
public byte mask_digital; // 1
public byte value_digital; // 1
public byte mask_analog; // 1
public byte reserved0; // 1
public short[] value_analog= new short[4]; // 8
public int pwm_frequency; // 4
public short pwm_value; // 2
public int reserved1; // 4
public int reserved2; // 4
public s_xl_daio_data() {
super();
}
}
The native Struct is 32 Bytes. If I print out the size of the struct with the .size()
operation from Structure it is 36 Bytes.
What are the 4 additional bytes?
The mappings are correct, but default structure alignments are creating extra padding in JNA, which assumes defaults unless told otherwise.
A way for you to confirm this and debug future structure size/alignment mismatches is to use the default Structure
class toString()
method. It prints each field's offset and value, so you can look for the misalignment of the offsets with your expectations.
s_xl_daio_data foo = new s_xl_daio_data();
System.out.println(foo.toString());
Inspecting the output of that code on my system shows two extra bytes after the first short
because int timestamp_correction
must start on a 4-byte boundary (0x4 rather than 0x2):
short flags@0x0=0x00
int timestamp_correction@0x4=0x0000
and two more extra bytes after the last short
because int reserved1
must start on a 4-byte boundary (0x1C rather than 0x1A):
short pwm_value@0x18=0x00
int reserved1@0x1C=0x0000
The default alignment often works with system DLLs which in many cases take structure alignment into account with explicit padding fields. However, sometimes other DLLs require no alignment, in which case you would specify this in JNA when instantiating the structure.
public s_xl_daio_data() {
super(Structure.ALIGN_NONE);
}
It would be useful to confirm this is giving you the expected data in the appropriate fields using the same toString()
noted earlier.