在JNA调用中使用ByteBuffer来表示字符串会导致缓冲区中出现额外的字符



我使用JNA和使用Jnaerator生成的代码调用dll。其中一个方法需要一个字符串,而JNA签名需要一个ByteBuffer。

我试过直接分配ByteBuffer (ByteBuffer. allocatedirect)和间接(ByteBuffer.wrap),但在这两种情况下有时到达dll的字符串有额外的随机字符(例如ReceiptÚeœ)。原始字节[]在那里(receive = 52 65 63 65 69 70 74),但也有一个可变数量的额外随机字节(01 da 65 9c 19)。字符串随机是正确的,没有额外的字节。

我已经尝试了等效的代码使用BridJ而不是JNA(方法签名然后一个指针名称),在这种情况下,它工作得很好。不幸的是,我不能切换到BridJ,因为我需要使用com.sun.jna.平台。win32类,除非我可以生成一个BridJ替代那些(https://stackoverflow.com/questions/31658862/jnaerator-bridj-user32-missing-methods)

本地声明:

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 call NOT working test A:

lpszLogicalName = ByteBuffer.wrap(bytes);
 MsxfsLibrary.INSTANCE.WFSOpen(lpszLogicalName, lphApp.getValue(), lpszAppID, dwTraceLevel, dwTimeOut, dwSrvcVersionsRequired, lpSrvcVersion, lpSPIVersion, lphService);

Java call NOT working test 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);

如果你指的是_wfsopen(),它期待一个宽字符字符串。要么使用WString,要么将库配置为类型映射String(参见W32APIOptions.UNICODE_OPTIONS)。

我认为正在发生的事情是你正在传递一个包含字符串的字节数组,但它不是null终止字符串。您应该创建一个具有额外位置的字节数组。将最后一个位置设置为0并将字符串复制到该字节数组中。

相关内容

  • 没有找到相关文章

最新更新