Java使用JNA调用DLL错误:内存访问无效

时间:2017-12-04 02:34:25

标签: java c++ dll hardware jna

我想调用dll来写入/读取硬件。但是,我得到以下错误:

DLL方法:

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

java方法:

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

api文档将cardno显示为out参数,track1,track2可以为null。

NativeLongByReference cardNo = new NativeLongByReference ();

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

它不起作用。所以我使用一种简单的方法:

dll method :

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

java方法:

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

NativeLong a = new NativeLong(0L);

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

它再次出现同样的错误:

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)

当我尝试使用dll方法从/向硬件读/写时,似乎只出现错误。

我该如何解决这个问题?

详情:win7 64 bite,jre1.8 32bite,jna4.1

2 个答案:

答案 0 :(得分:0)

如果要从dll访问内存,则需要设置引用内存位置所需的正确数据类型。在指针对象上,你的jna应该使用ByteByReference作为char *,或者你也可以使用PointerByReference而不是将对象声明为String。使用PointerByReference将帮助您避免内存泄漏。

JNA Marshalling / Unmarshalling

是个好地方。祝你好运!

编辑: Java方法声明 - (JNA XXByReference用法示例)

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

Java用法 -

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

从你的例子:

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

您必须调整方法代码才能获得实际的指针值。

答案 1 :(得分:0)

我想" MainDll"有多个依赖。

当我将所有需要的依赖项dll放在项目文件夹根路径下时 使用相对路径来加载我的dll,它最终成功了。

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