Распределение памяти JNA структуры не соответствует

#java #structure #jna #allocation

#java #структура #jna #распределение

Вопрос:

структура в моем машинном коде:

 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
};
  

мой класс 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 байта. Если я распечатаю размер структуры с .size() помощью операции из Structure, он составит 36 байт.

Каковы 4 дополнительных байта?

Ответ №1:

Сопоставления верны, но выравнивания структуры по умолчанию создают дополнительное заполнение в JNA, которое предполагает значения по умолчанию, если не указано иное.

Способ подтвердить это и отладить будущие несоответствия размера / выравнивания структуры — использовать Structure 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 не требуют выравнивания, и в этом случае вы должны указать это в JNA при создании экземпляра структуры.

 public s_xl_daio_data() {
    super(Structure.ALIGN_NONE);
}
  

Было бы полезно подтвердить, что это дает вам ожидаемые данные в соответствующих полях, используя то же toString() самое, что указано ранее.