英文:
JNA memory allocation of Structure does not match
问题
本地代码中的结构体:
```c
struct s_xl_daio_data { /* 32字节 */
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
};
我的Java类:
@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();
}
}
本地结构体的大小为32字节。如果我使用Structure的.size()
操作打印出结构体的大小,结果是36字节。
那4个额外的字节是什么?
<details>
<summary>英文:</summary>
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?
</details>
# 答案1
**得分**: 1
映射是正确的,但是[默认结构对齐][1]在JNA中创建了额外的填充,JNA假定使用默认值,除非另有说明。
您可以确认这一点并调试将来的结构大小/对齐不匹配问题,方法是使用默认的`Structure`类的`toString()`方法。它会打印每个字段的偏移和值,这样您就可以查找偏移与您预期不匹配的情况。
```java
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()
方法,确认这是否为您提供了预期的数据在适当的字段中将会很有用。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论