Я вызываю dll с использованием JNA и кода, сгенерированного с использованием Jnaerator. Один из методов требует строки, а подписи JNA принимает ByteBuffer.Использование ByteBuffer для представления строки в вызове JNA приводит к дополнительным символам в буфере
Я попытался выделения ByteBuffer как прямой (ByteBuffer.allocateDirect) и непрямого (ByteBuffer.wrap), но в обоих случаях несколько раз строка, которая достигает DLL имеет дополнительные случайные символы (например, ReceiptÚeœ). Исходный байт [] есть (получение = 52 65 63 65 69 70 74), но также переменное количество дополнительных случайных байтов (01 da 65 9c 19). Случайно строка правильная, без дополнительных байтов.
Я пробовал эквивалентный код, используя BridJ вместо JNA (подпись метода принимает тогда имя указателя), и в этом случае он отлично работает. К сожалению, я не могу переключиться на BridJ, потому что мне нужно использовать классы com.sun.jna.platform.win32, если я не могу произвести замену BridJ для тех, кто (https://stackoverflow.com/questions/31658862/jnaerator-bridj-user32-missing-methods)
Native декларация:
HRESULT extern WINAPI WFSOpen (LPSTR lpszLogicalName, HAPP hApp, LPSTR lpszAppID,DWORD dwTraceLevel, DWORD dwTimeOut, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion, LPWFSVERSION lpSPIVersion, LPHSERVICE lphService);
JNAerator ЮНА код:
//works
@Deprecated
NativeLong WFSOpen(Pointer lpszLogicalName, Pointer hApp, Pointer lpszAppID, int dwTraceLevel, int dwTimeOut, int dwSrvcVersionsRequired, WFSVERSION lpSrvcVersion, WFSVERSION lpSPIVersion, ShortByReference lphService);
//does not work
NativeLong WFSOpen(ByteBuffer lpszLogicalName, Pointer hApp, ByteBuffer lpszAppID, int dwTraceLevel, int dwTimeOut, int dwSrvcVersionsRequired, WFSVERSION lpSrvcVersion, WFSVERSION lpSPIVersion, ShortBuffer lphService);
Java вызов работает (но не рекомендуется)
Pointer m = new Memory(string.length() + 1); // WARNING: assumes ascii-only string
m.setString(0, string);
MsxfsLibrary.INSTANCE.WFSOpen(lpszLogicalName, lphApp.getValue(), lpszAppID, dwTraceLevel, dwTimeOut, dwSrvcVersionsRequired, lpSrvcVersion, lpSPIVersion, lphService);
Java вызов НЕ работает тест A:
lpszLogicalName = ByteBuffer.wrap(bytes);
MsxfsLibrary.INSTANCE.WFSOpen(lpszLogicalName, lphApp.getValue(), lpszAppID, dwTraceLevel, dwTimeOut, dwSrvcVersionsRequired, lpSrvcVersion, lpSPIVersion, lphService);
Java вызов НЕ работает тест B:
byte[] bytes = string.getBytes();
return ByteBuffer.wrap(bytes);
ByteBuffer bb = ByteBuffer.allocateDirect(bytes.length);
bb.put(bytes);
lpszLogicalName = bb.position(0);
msxfsLibrary.WFSOpen(lpszLogicalName, lphApp.getValue(), lpszAppID, dwTraceLevel, dwTimeOut, dwSrvcVersionsRequired, lpSrvcVersion, lpSPIVersion, lphService);
Ожидающий код? Какова ваша собственная декларация? Каково ваше отображение на Java? Является ли ваш собственный код ожидаемым 'const char *' или 'const wchar_t *'? Обычно JNA отображает 'String' в первый, но это поведение может быть различным в зависимости от того, как вы инициализируете отображение вашей библиотеки. Почему бы просто не сменить подпись, чтобы взять «String», если это то, что ожидает собственный код? – technomage
Уроженец декларация: 'HRESULT ехЬегп WINAPI WFSOpen (LPSTR lpszLogicalName' Jnaerator ЮНА не удается случайным образом, переводит: ' NativeLong WFSOpen (ByteBuffer lpszLogicalName, ... ' Jnaerator Bridj работает отлично, переводится: ' общественного статики длинный WFSOpen (Pointer lpszLogicalName' –
movees
Обновите свой вопрос и удалите эти комментарии. – technomage