JNA. Создание структуры из указателя

334
01 июля 2017, 09:41

Добрый день, коллеги!
Возникла необходимость плотно поработать с WinApi из Java. JNI не хочу использовать из-за лени переключаться между средами, компиляторами и т.д. - решил применить широкоизвестный фреймворк JNA. Суть проблемы в следующем:

Имеется замечательная функция GetIfTable которая имеет следующую сигнатуру:

DWORD GetIfTable(
  _Out_   PMIB_IFTABLE pIfTable,
  _Inout_ PULONG       pdwSize,
  _In_    BOOL         bOrder
);

Как видно она работает со структурой MIB_IFTABLE имеющей следующий вид:

typedef struct _MIB_IFTABLE {
  DWORD     dwNumEntries;
  MIB_IFROW table[ANY_SIZE];
} MIB_IFTABLE, *PMIB_IFTABLE;

Если почитать MSDN про данную функцию, то можно увидеть интересный способ ее применения:

  1. Передаем в функцию созданную по умолчанию структуру и ее размер (либо null и dwSize = 0) в ответ, функция вернет нам ошибку буфера и запишет в dwSize количество байт памяти которые необходимо выделить для хранения выходного результата.
  2. Выделяем память и повторно вызываем метод. Он возвращает 0 - все ок. Берем полученный массив структур и работаем по нему.

Применительно к Java и JNA в данном случае возникает проблема - невозможно объявить в структуре массив неизвестной длинны, а значит придется работать с указателями (P.S> сразу оговорюсь если работать не с указателями, а с инстансами структур, указав например массив table равным 1000 элементам, то все отработает более менее корректно).

Объявляем структуры и функции:

class MIB_IFTABLE extends Structure {
        public static class ByReference extends MIB_IFTABLE implements Structure.ByReference {}
        public static class ByValue extends MIB_IFTABLE implements Structure.ByValue { }
        public WinDef.DWORD dwNumEntries = new WinDef.DWORD();   //Количество интерфейсов в массиве
        public Pointer table = Pointer.NULL;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(new String[]{"dwNumEntries", "table"});
        }
        public MIB_IFTABLE() {
        }
        public MIB_IFTABLE(Pointer p) {
            super(p);
        }
    }
    int GetIfTable(Pointer pIfTable, ULONGByReference pwdSize, WinDef.BOOL bOrder);

Ну и пробуем со всем этим поработать:

Pointer pIfTable = Pointer.NULL;
WinApiHelper helper = WinApiHelper.INSTANCE;
WinDef.ULONGByReference dwSize = new WinDef.ULONGByReference(new WinDef.ULONG(0));
int res = helper.GetIfTable(pIfTable, dwSize, new WinDef.BOOL(false));
pIfTable = new Memory(dwSize.getValue().longValue());
res = helper.GetIfTable(pIfTable, dwSize, new WinDef.BOOL(false));
WinApiHelper.MIB_IFTABLE table = new WinApiHelper.MIB_IFTABLE(pIfTable);

И вот тут-то наступает нежданчик - данные в tableотсутствуют! Т.е. структура не создалась и незаполнилась по переданному ей указателю. Причем если посмотреть на данные по указателю pIfTable - то они там очень даже есть, но вот добраться до них нормально я не могу. Как быть?

Answer 1

После создания структуры по указателя надо было выполнить метод read().

READ ALSO
Toolbar возвращает null

Toolbar возвращает null

Всем доброго времени суток! Есть фрагмент, в котором реализуется ToolbarВ нем есть метод:

245
Можно ли установить ClickListener на края экрана?

Можно ли установить ClickListener на края экрана?

Есть несколько экранов, оформлено с помощью flipper, переключаюсь по кнопкам (влево,вправо)

203
Vector, Hashtable. В чем минус синхронизированности?

Vector, Hashtable. В чем минус синхронизированности?

Vector, HashTable, Stack являются устаревшими коллекциями, и пишут что их не используют в виду синхронизированности их методовВ чем минус синхронизации?...

267
Шейдеры и ShapeRendere. LibGDX

Шейдеры и ShapeRendere. LibGDX

Пытаюсь применить ShaderProgram к ShapeRenderer, передаю шейдер в конструктор, получаю ошибку:

286