2015-07-28 2 views
0

J'appelle une DLL en utilisant JNA et du code généré en utilisant Jnaerator. L'une des méthodes nécessite une chaîne, et la signature JNA prend un ByteBuffer.L'utilisation d'un ByteBuffer pour représenter une chaîne dans un appel JNA entraîne des caractères supplémentaires dans le tampon

J'ai essayé allouer le ByteBuffer aussi direct (ByteBuffer.allocateDirect) et indirecte (ByteBuffer.wrap), mais dans les deux cas quelques fois la chaîne qui atteint la dll a d'autres caractères aléatoires (par exemple ReceiptÚeœ). L'octet original [] est là (reçu = 52 65 63 65 69 70 74) mais aussi un nombre variable d'octets aléatoires supplémentaires (01 da 65 9c 19). Aléatoirement, la chaîne est correcte, sans octets supplémentaires.

J'ai essayé le code équivalent en utilisant BridJ au lieu de JNA (la signature de la méthode prend alors un nom de Pointer) et dans ce cas, cela fonctionne bien. Malheureusement, je ne peux pas passer à BridJ parce que je dois utiliser les classes com.sun.jna.platform.win32, à moins que je peux générer un remplacement BridJ pour ceux (https://stackoverflow.com/questions/31658862/jnaerator-bridj-user32-missing-methods)

déclaration native:

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

JNAerator Code 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); 

appel Java de travail (mais dépréciée)

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

appel Java Test de personnalité de travail A:

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

test de l'appel ne fonctionne PAS 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

À quoi s'attend votre code natif? Quelle est votre déclaration native? Quelle est votre cartographie Java? Est-ce que votre code natif attend 'const char *' ou 'const wchar_t *'? Normalement, JNA mappe 'String' à l'ancien, mais ce comportement peut être différent selon la façon dont vous initialisez le mappage de la bibliothèque. Pourquoi ne pas simplement changer la signature pour prendre un 'String' si c'est ce que le code natif attend? – technomage

+0

La déclaration est native: 'HRESULT extern WINAPI WFSOpen (LPSTR lpszLogicalName' JNA Jnaerator échoue au hasard, se traduit par: ' NativeLong WFSOpen (ByteBuffer lpszLogicalName, ... ' Jnaerator Bridj fonctionne très bien, se traduit par: ' public static long WFSOpen (Pointer lpszLogicalName' – movees

+0

Mettez à jour votre question et supprimez ces commentaires – technomage

Répondre

0

Si vous faites référence à _wfsopen(), il attend un chaîne de caractères larges. Utilisez WString ou configurez votre bibliothèque pour taper String (voir W32APIOptions.UNICODE_OPTIONS).

+0

Non, ce n'est pas le studio visuel wfsopen, c'est le CEN-XFS, qui prend un LPSTR lpszLogicalName comme premier paramètre. – movees

0

Je pense que ce qui se passe est que vous passez un tableau d'octets qui contient votre chaîne, mais ce n'est pas une chaîne terminée par un caractère nul. Vous devez créer un tableau d'octets avec une position supplémentaire. Définissez cette position à 0 et copiez votre chaîne dans ce tableau d'octets.