1

I want to call dll to write/read from hardware.However, I get the error below:

dll method:

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

java method:

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

The api document shows cardno as a out parameter and track1,track2 could be null.

NativeLongByReference cardNo = new NativeLongByReference ();

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

It don t work. So I use a simple method:

dll method :

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

java method:

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

NativeLong a = new NativeLong(0L);

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

It gets the same error again:

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)

It seems like the error only occurs when I try to use the dll methods to read/write from/to hardware.

How can I solve the problem?

details: win7 64 bite, jre1.8 32bite, jna4.1

zhatian diao
  • 163
  • 1
  • 9
  • I just seen your using the 32 bit java. I have had some trouble with some c string conversion between 64 bit os and 32 bit java. However, it looks like it is loading ok. – Tim Strawbridge Dec 06 '17 at 23:43

2 Answers2

1

If you want to access memory from the dll, you will need to setup the proper data type needed to reference the memory location. On pointer objects your jna should use ByteByReference for char* or you can also use PointerByReference instead of declaring the object as a String. Using PointerByReference will help you avoid memory leaks.

JNA Marshalling / Unmarshalling

is a good place to start. Good Luck!

Edit: Java method declaration - (example of JNA XXByReference usage)

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

Java usage -

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

From your example:

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

You will have to adjust your methods code to get the actual pointers value.

Tim Strawbridge
  • 646
  • 4
  • 9
  • I googled jna mapping, it seems that C "char *" map to java "String". My other jna methods using “String” to invoke “char *” as input variables just worked fine except the ones involve hardware read/write.It seems not the "char *" problem. Anyway,thanks! – zhatian diao Dec 06 '17 at 03:23
  • I just want to use thos "char *" as input variables without out parameters.The method "newKey" s only out parameter is " NativeLongByReference cardno".That s why I use NativeLongByReference only.I tried your advice for changing to pointer like below: String guestName = "GuestName"; Pointer guestNameP = new Memory(guestName.length() + 1); guestNameP.setString(0, guestName); PointerByReference guestNamePR = new PointerByReference(guestNameP); it dont work. – zhatian diao Dec 07 '17 at 03:46
  • What hardware device are using? My example code was if you are reading from a device. You would also need to think about what is allocating memory. If its the DLL then the PointerByReference will work. If its the Java code and your passing pointers to the DLL then your on the right track with using new Memory(); I would like to see the actual DLL's functions, that way its not so much of a guessing game. – Tim Strawbridge Dec 07 '17 at 04:54
  • Actual it s a device to write informations to cards. So the cards can open hotel door in several days.That is why the dll has "newKey" method and "EraseCard" method. When hotel guest checkin, we call newkey method to create a card. when guest checkout,we erase the card. – zhatian diao Dec 07 '17 at 06:49
1

I guess the "MainDll" have multi dependencies.

When I put all my needed dependcies dll under the project folder root path and use relative path to load my my dll, it finally successed.

    CLibrary INSTANCE = (CLibrary) Native.synchronizedLibrary((CLibrary) Native.loadLibrary("MainDll", CLibrary.class));
zhatian diao
  • 163
  • 1
  • 9