2017-12-04 3 views
0

Ich möchte, erhalte ich den Fehler unten:Java verwenden JNA Aufruf dll Fehler: DLL rufen zu schreiben/lesen von hardware.However ungültigen Speicherzugriff

dll-Methode:

int NewKey(char *room,char *gate,char *stime,char *guestname,char *guestid, int overflag, int Breakfast, long *cardno,char * track1,char * track2); 

java methode:

Das api-Dokument zeigt cardno als out-Parameter und track1, track2 könnte null sein.

NativeLongByReference cardNo = new NativeLongByReference(); 

int res = CLibrary.INSTANCE.NewKey("010001", "00", "201712021200201712031200", "Guest Name","Account No.", 0, 1, cardNo, null, null); 

Es funktioniert nicht. So verwende ich eine einfache Methode:

dll method : 

int EraseCard (long cardno,char * track1,char * track2); 

Java-Methode:

int EraseCard(NativeLong cardno, String track1, String track2); 

NativeLong a = new NativeLong(0L); 

int res = CLibrary.INSTANCE.EraseCard (a, null, null); 

Es erhält den gleichen Fehler wieder:

Exception in thread "main" java.lang.Error: Invalid memory access 
at com.sun.jna.Native.invokeInt(Native Method) 
at com.sun.jna.Function.invoke(Function.java:383) 
at com.sun.jna.Function.invoke(Function.java:315) 
at com.sun.jna.Library$Handler.invoke(Library.java:212) 
at A90PmsInterface.main(A90PmsInterface.java:104) 

Es scheint, wie der Fehler tritt nur auf, wenn ich Versuchen Sie, die DLL-Methoden zum Lesen/Schreiben von/zur Hardware zu verwenden.

Wie kann ich das Problem lösen?

Details: win7 64 Biss, jre1.8 32bite, jna4.1

+0

Ich habe gerade gesehen, wie Sie das 32-Bit-Java verwenden. Ich hatte einige Probleme mit einigen c-String-Konvertierung zwischen 64-Bit-OS und 32-Bit-Java. Es sieht jedoch so aus, als ob es ok geladen wird. – TBridges

Antwort

0

Wenn Sie Speicher aus dem DLL zugreifen möchten, werden Sie den richtigen Datentyp Setup benötigen Sie den Speicherort verweisen benötigt. Bei Zeigerobjekten sollte Ihre jna ByteByReference für char * verwenden oder Sie können PointerByReference auch verwenden, anstatt das Objekt als String zu deklarieren. Mit PointerByReference können Sie Speicherlecks vermeiden.

JNA Marshalling/Unmarshalling

ist ein guter Anfang. Viel Glück!

Edit: Java Methodendeklaration - (Beispiel JNA XXByReference Nutzung)

public int E1K_DI_Reads(int connection, byte channel, byte channelCount, IntByReference value); 

Java-Nutzung -

public int readDI(int connection, byte channel, byte count){ 
    IntByReference refValue = new IntByReference(); 
    lib.E1K_DI_Reads(connection, channel, count, refValue); 
    int value = refValue.getValue(); 
    return value; 
} 

Von Ihrem Beispiel:

int NewKey(PointerByReference room, PointerByReference gate,PointerByReference time,PointerByReference guestname,PointerByReference guestid, int overflag, int Breakfast, NativeLongByReference cardno, PointerByReference track1, PointerByReference track2); 

Sie müssen Passen Sie Ihren Methodencode an, um den tatsächlichen Zeigerwert zu erhalten.

+0

Ich googled jna Mapping, es scheint, dass C "char *" zu Java "String" zuordnen. Meine anderen jna-Methoden, die "String" verwenden, um "char *" als Eingabevariablen aufzurufen, funktionierten gut, mit Ausnahme der Hardware-Lese-/Schreiboperationen. Es scheint nicht das "char *" - Problem zu sein. Trotzdem danke! –

+0

@ zhatian diao, siehe die bearbeitete Antwort. – TBridges

+0

Ich möchte nur thos "char *" als Eingabevariablen ohne out-Parameter verwenden. Die Methode "newKey" nur out-Parameter ist "NativeLongByReference cardno" .Deswegen verwende ich nur NativeLongByReference.Ich habe versucht Ihren Tipp für den Zeiger zu ändern unten: String guestName = "GuestName"; Zeiger guestNameP = new Memory (guestName.length() + 1); guestNameP.setString (0, GastName); PointerByReference guestNamePR = new PointerByReference (guestNameP); es funktioniert nicht. –

0

Ich denke, die "MainDll" haben mehrere Abhängigkeiten.

Wenn ich alle meine benötigten dependcies dll unter dem Projektordner Root-Pfad und relativer Pfad, um meine meine DLL zu laden, fügte es schließlich nach.

CLibrary INSTANCE = (CLibrary) Native.synchronizedLibrary((CLibrary) Native.loadLibrary("MainDll", CLibrary.class));