2015-07-28 142 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並將您的字符串複製到該字節數組中。

相關問題