Массив структур в структуре в JNA

#java #jna

#ява #юна #java #jna

Вопрос:

Мой машинный код — это

 typedef struct driver_config {
    unsigned int dllVersion;
    unsigned int channelCount;
    unsigned int reserved[10];
    ChannelConfig channel[64];
} DriverConfig;
  

В Java мой класс выглядит следующим образом

 public class DriverConfig extends Structure {
    
    public int dllVersion;
    public int channelCount;
    public int[] reserved= new int[10];
    ChannelConfig[] channel = new ChannelConfig[64];
    
    public DriverConfig() {
        super();
        init();     
    }
    
    private void init() {
        for (int i = 0; i < channel.length; i  ) {
            channel[i]= new ChannelConfig();
        }
    }

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList(new String[] { "dllVersion", "channelCount", "reserved" });
    }

    //toString()...
}
  

Объявление метода является

 int getDriverConfig(DriverConfig driverConfig);
  

Я попытался получить доступ к методу следующим образом

 DriverConfig driverConfig = new DriverConfig();
status = dll.INSTANCE.getDriverConfig(driverConfig);
System.out.println("DriverConfig Status: "   status);
System.out.println(driverConfig.toString());
  

Если channel.length заменяется на значение менее 50, массив инициализируется правильно, но с channel.length это не сработало. Он даже не показал никакой ошибки, просто ничего.

Комментарии:

1. channel Должно быть в полевом порядке?

2. Я не уверен, что это точно означает, если что-то есть в getFieldOrder(). Сначала я попытался с каналом, но затем произошла ошибка

3. И в чем была ошибка?

4. Structure.getFieldOrder() в классе DriverConfig предоставляет слишком много имен [4] ([channel, channelCount, dllVersion, зарезервировано]), чтобы соответствовать объявленным полям [3] ([channelCount, dllVersion, зарезервировано])

Ответ №1:

Ваш getFieldOrder() массив не включает последний элемент ( channel ) вашей структуры. Я вижу в ваших комментариях, что вы пытались это сделать, но получили ошибку, потому что вы ее не объявили public . Все элементы вашей структуры должны быть перечислены в FieldOrder , а также объявлены public , чтобы их можно было найти с помощью отражения.

Кроме того, с JNA 5.x (который вы должны использовать) @FieldOrder аннотация является предпочтительной.

Вы не определили сопоставление для ChannelConfig , но заголовок вашего вопроса и эта ссылка на API, соответствующая вашей структуре, указывают, что это вложенный структурный массив. Массивы структур должны быть выделены с использованием непрерывной памяти, либо путем непосредственного выделения собственной памяти ( new Memory() ), что требует знания размера структуры, либо с помощью Structure.toArray() . Выделение в цикле, как вы сделали, приведет к выделению памяти для каждой новой структуры, выделенной в возможных / вероятных несмежных местоположениях в собственной памяти. Учитывая, что вы заявляете, что это, по-видимому, работает для некоторых значений, возможно, вам повезло с непрерывными распределениями, но ваше поведение, безусловно, не определено.

Поэтому ваше отображение структуры должно быть:

 @FieldOrder ({"dllVersion", "channelCount", "reserved", "channel"})
public class DriverConfig extends Structure {
    public int dllVersion;
    public int channelCount;
    public int[] reserved= new int[10];
    public ChannelConfig[] channel = (ChannelConfig[]) new ChannelConfig().toArray(64);
}