结构的 JNA 内存分配不匹配
JNA memory allocation of Structure does not match
我本机代码中的结构:
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
};
我的Javaclass:
@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();
}
}
原生 Struct 是 32 字节。如果我使用 Structure 中的 .size()
操作打印出结构的大小,它是 36 字节。
额外的 4 个字节是什么?
映射是正确的,但是 default structure alignments 在 JNA 中创建了额外的填充,除非另有说明,否则它采用默认值。
确认这一点并调试未来结构 size/alignment 不匹配的一种方法是使用默认的 Structure
class toString()
方法。它打印每个字段的偏移量和值,因此您可以查找偏移量是否与您的预期不一致。
s_xl_daio_data foo = new s_xl_daio_data();
System.out.println(foo.toString());
在我的系统上检查该代码的输出显示在第一个 short
之后有两个额外的字节,因为 int timestamp_correction
必须从 4 字节边界开始(0x4 而不是 0x2):
short flags@0x0=0x00
int timestamp_correction@0x4=0x0000
和最后一个 short
之后的两个额外字节,因为 int reserved1
必须从 4 字节边界开始(0x1C 而不是 0x1A):
short pwm_value@0x18=0x00
int reserved1@0x1C=0x0000
默认对齐通常与系统 DLL 一起使用,在许多情况下,系统 DLL 会使用显式填充字段来考虑结构对齐。但是,有时其他 DLL 不需要对齐,在这种情况下,您可以在实例化结构时在 JNA 中指定它。
public s_xl_daio_data() {
super(Structure.ALIGN_NONE);
}
确认这是否使用前面提到的 toString()
在适当的字段中为您提供预期数据会很有用。
我本机代码中的结构:
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
};
我的Javaclass:
@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();
}
}
原生 Struct 是 32 字节。如果我使用 Structure 中的 .size()
操作打印出结构的大小,它是 36 字节。
额外的 4 个字节是什么?
映射是正确的,但是 default structure alignments 在 JNA 中创建了额外的填充,除非另有说明,否则它采用默认值。
确认这一点并调试未来结构 size/alignment 不匹配的一种方法是使用默认的 Structure
class toString()
方法。它打印每个字段的偏移量和值,因此您可以查找偏移量是否与您的预期不一致。
s_xl_daio_data foo = new s_xl_daio_data();
System.out.println(foo.toString());
在我的系统上检查该代码的输出显示在第一个 short
之后有两个额外的字节,因为 int timestamp_correction
必须从 4 字节边界开始(0x4 而不是 0x2):
short flags@0x0=0x00
int timestamp_correction@0x4=0x0000
和最后一个 short
之后的两个额外字节,因为 int reserved1
必须从 4 字节边界开始(0x1C 而不是 0x1A):
short pwm_value@0x18=0x00
int reserved1@0x1C=0x0000
默认对齐通常与系统 DLL 一起使用,在许多情况下,系统 DLL 会使用显式填充字段来考虑结构对齐。但是,有时其他 DLL 不需要对齐,在这种情况下,您可以在实例化结构时在 JNA 中指定它。
public s_xl_daio_data() {
super(Structure.ALIGN_NONE);
}
确认这是否使用前面提到的 toString()
在适当的字段中为您提供预期数据会很有用。