Добро пожаловать в чудесный мир кодировки символов .
Вы используете Native.toByteArray () только с аргументом String
. Это возвращает:
байтовый буфер с завершающим нулем, эквивалентный заданной строке, с использованием кодировки, возвращаемой getDefaultStringEncoding ().
Как правило, оставлять кодировка не указана при преобразовании между строками и байтовыми массивами. В этом случае вам действительно нужна системная кодировка по умолчанию, но полезно указать это и в процессе понять, что он делает.
Кодировка Windows по умолчанию - UTF-16, которая использует 16 биты для представления символов (wchar_t
в C). Для символьных строк ASCII, подобных тем, которые вы используете, это означает, что ваш байтовый массив заканчивается чередованием байтов 0 и 8-битных символов. (Не стесняйтесь инструментировать свой код и вывести Arrays.toString(f1)
, чтобы убедиться в этом сами!)
Структура C использует массивы TCHAR
. Это может быть один или два байта, в зависимости от вашей кодировки (которая соответствует Native.toByteArray()
).
Таким образом, кодировка по умолчанию здесь подходит, за исключением того, что вам нужно знать, что это за кодировка, чтобы правильно определить размер вашей структуры. Вы передаете 512-байтовые массивы, когда вам, вероятно, нужны массивы 512-TCHAR (1024 байта). Однако
структуры JNA должны знать свой общий размер в байтах, а TCHAR
не отображается в JNA. Итак, вам нужно вычислить CHAR_WIDTH
и умножить 512 на это значение в структуре. (Найдите в исходном коде JNA CHAR_WIDTH
, чтобы найти достаточное количество примеров этого.)
(EDIT 1)
Спасибо за предоставление сопоставления JNA. Обычно самое первое, на что следует обратить внимание, когда JNA-отображенная функция / структура плохо себя ведет, - это отображение типов. В вашем случае, в дополнение к неправильному сопоставлению TCHAR
с byte
, как описано выше, вы сопоставили HANDLE
как NativeLong
. Это не работает с Windows: HANDLE
расширяется от PointerType
, а указатели соответствуют разрядности операционной системы, поэтому 64-разрядные на 64-разрядных Windows. Windows LONG
с другой стороны (и, следовательно, NativeLong
на Windows) всегда 32-битный тип.
Итак, чтобы подвести итог, вам потребуются (как минимум) следующие изменения:
Измените типы HANDLE
для сопоставления с WinNT.HANDLE
классом JNA
Измените ширину TCHAR
байта в соответствии с шириной символа. Один из способов сделать это - вставить это в начало вашего класса (или где угодно в вашем проекте, publi c, чтобы он был доступен):
private static final int CHAR_WIDTH = Boolean.getBoolean("w32.ascii") ? 1 : 2;
Затем в вашем byte[]
объявления, умножьте 512 * CHAR_WIDTH
, чтобы получить правильную ширину.