2015-07-28 140 views
0

我使用JNA和使用Jnaerator生成的代码调用dll。其中一种方法需要一个字符串,而JNA签名需要一个ByteBuffer。使用ByteBuffer表示JNA调用中的字符串会导致缓冲区中出现额外的字符

我已经试过分配字节缓冲区为直接(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

本地声明:

HRESULT extern WINAPI WFSOpen (LPSTR lpszLogicalName, HAPP hApp, LPSTR lpszAppID,DWORD dwTraceLevel, DWORD dwTimeOut, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion, LPWFSVERSION lpSPIVersion, LPHSERVICE lphService); 

JNAerator JNA代码:

//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调用不工作的测试答:

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); 
+0

你的本地代码期望什么?你的母语是什么?什么是Java映射?你的本地代码是否期望'const char *'或'const wchar_t *'?通常情况下,JNA会将'String'映射到前者,但根据初始化库映射的方式,这种行为可能会有所不同。如果这是本机代码的期望,为什么不更改签名以接受'String'? – technomage

+0

本机声明: 'HRESULT的extern WINAPI WFSOpen(LPSTR lpszLogicalName' Jnaerator JNA随机失败,翻译过来就是: 'NativeLong WFSOpen(ByteBuffer的lpszLogicalName,...' Jnaerator Bridj工作正常,翻译过来就是: '公共静态长WFSOpen(指针 lpszLogicalName' – movees

+0

更新您的问题,并删除这些评论。 – technomage

回答

0

如果你指的是_wfsopen(),它期待一个宽字符串。请使用WString,或将库配置为键入映射String(请参阅W32APIOptions.UNICODE_OPTIONS)。

+0

不,它不是视觉工作室wfsopen,它是CEN-XFS,它将LPSTR lpszLogicalName作为第一个参数。 – movees

0

我认为发生的事情是您传递的字节数组包含您的字符串,但它不是以空字符结尾的字符串。您应该创建一个具有额外位置的字节数组。将las位置设置为0并将您的字符串复制到该字节数组中。

相关问题