Есть ли конкретный способ иметь дело с константными указателями членов структуры в JNA? - PullRequest
1 голос
/ 27 марта 2019

У меня есть следующая структура C:

typedef struct {
    void           *instance;
    const info_st  *info;
} core_st;

, которую я сопоставляю со следующим Java-классом, используя JNA:

public class core_st extends Structure {

    public Pointer instance;
    public info_st.ByReference info;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("instance", "info");
    }
}

У меня также есть следующая функция, взятая из dll:

uint32_t open_core(uint32_t core_id, core_st **core);

И относительное отображение JNA:

int open_core(int core_id, core_st[] core);

Наконец, я написал Java-программу, которая вызывает функцию следующим образом:

core_st[] cores = new core_st[1];
MyLibrary.INSTANCE.open_core(0, cores);

Функция должназаполнить cores[0] членов результатом операции "open".В частности, два поля являются двумя указателями на что-то еще.Что происходит, так это то, что поле void *instance всегда заполнено правильно, но поле info всегда равно нулю (указатель на ноль).Если я установлю для jna.memory_dump значение true, любой вызов core_st.toString() всегда будет возвращать один и тот же результат:

memory dump
[70cb64e7]
[fd7f0000]
[00000000]
[00000000]

Это похоже на указатель на info структура не находится в памяти, прочитанной JNA.Один и тот же вызов, выполняемый аналогичной программой на C, работает нормально, оба указателя заполнены правильно.Я также попытался изменить отображение core_st , просто для целей тестирования:

public class core_st extends Structure {

    public long instance;
    public long info;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("instance", "info");
    }
}

Но я не получил никаких различий в результате. экземпляр получает ненулевое значение, а info всегда равно нулю.Я работаю с 64-битной виртуальной машиной.Мне было интересно, может ли быть проблема в модификаторе const поля info ?Может ли модификатор const в поле структуры указателя типа изменить способ хранения структуры в памяти?

1 Ответ

0 голосов
/ 30 марта 2019

Может ли модификатор const в поле структуры указателя типа изменить способ хранения структуры в памяти?

Ответ возможно , зависит от компилятора. Более важным для вашего вопроса является то, как const влияет на способ доступа к полю на нативной стороне. Независимо от того, что вы делаете на стороне Java, после инициализации поля info вашей структуры core_st вы не сможете его изменить.

И именно поэтому вы видите то, что видите здесь: определяя public info_st.ByReference info;, вы инициализируете структуру core_st указателем на NULL и получаете адрес памяти 0x0, сохраненный для этого поля. При доступе к этому полю с помощью API вы не можете изменить адрес памяти, он застрял.

Вы видите те же результаты, инициализирующие его как long со значением по умолчанию (0).

Решение зависит от того, как API заполняет это значение. Если на нативной стороне функция open_core предполагает, что поле info уже инициализировано с указателем на выделенную структуру, и просто изменяет значения в указанной памяти, все готово. Вам просто нужно инициализировать это поле при первом создании структуры.

Вы ничего не говорите мне о том, на что указывает *info, поэтому ответ будет разным в зависимости от того, массив это info_st структур или одна структура. Если это одна структура, у вас есть:

public class core_st extends Structure {

    public Pointer instance;
    public info_st.ByReference info = new info_st.ByReference();

}

Это выделит соответствующую память для структуры info_st и сохранит указатель только для чтения в вашей структуре core_st. В зависимости от внутренней работы open_core() (и на основании вашего отчета это работает на стороне C), это может сработать!

Если нет, возможно, размещение рабочего кода C поможет определить, есть ли другое сопоставление JNA, которое могло бы помочь, или вам нужно обойти его с помощью собственной пользовательской функции-оболочки dll.

...