JNA:EXCEPTION_ACCESS_VIOLATION

JNA: EXCEPTION_ACCESS_VIOLATION

我正在通过 JNA 使用 C++ DLL。 我想在Java中调用下面的方法,将我要读取的信息写入szVisor。

long FAR PASCAL DLL_GetLocalPortTS(char* szEquip,char* szVisor){
    ...
}

Java接口实现如下:

public interface IE2E extends Library {
    // Instancia de la dll, carga la librería
    IE2E INSTANCE = (IE2E) Native.loadLibrary("e2e", IE2E.class);
    ...
    int GetLocalPortTS(String equip, String[] equipInfo);
}

方法调用:

String equip = "equipID";
String equipInfo = "";
String[] rEquipInfo = {equipInfo};
IE2E sdll = IE2E.INSTANCE; 

int ret = sdll.GetLocalPortTS(equip, rEquipInfo);

此执行使我在 JRE 中遇到致命错误,但如果我将两个参数都作为 String 或 String[] 则不会。但是,如果我同时使用这两个字符串,它不会覆盖 equipInfo 并且我得不到我想要的信息;如果我将两者都用作数组,则该方法不会获得装备值并且不会运行。

欢迎提出任何见解。

问题是C代码要写入szVisor,对吧?我想它会做这样的事情:

long GetLocalPortTS(char* szEquip,char* szVisor){
    strcpy(szVisor, "I am C code result :)");
    return 0;
}

如果您从Java 端传入一个字符串,则内存归JVM 所有,因此写入它会导致崩溃。您需要的是一个 Memory 对象,它是 C 代码可以安全写入的包装的 malloc 内存位。

您的新 JNA 界面如下所示。我已经注释掉了旧版本所以你可以比较:

public interface IE2E extends Library {
    IE2E INSTANCE = (IE2E) Native.loadLibrary("e2e", IE2E.class);
    //int GetLocalPortTS(String equip, String[] equipInfo);
    int GetLocalPortTS(String equip, Memory equipInfo);
}

调用它的代码如下,256 是一个占位符。确保分配足够的空间将字符串写入:

String equip = "equipID";
String equipInfo = "";
//String[] rEquipInfo = {equipInfo};
Memory rEquipInfo = new Memory(256);
IE2E sdll = IE2E.INSTANCE;
int ret = sdll.GetLocalPortTS(equip, rEquipInfo);

要将结果用作字符串,您可以这样做:

rEquipInfo.getString(0);

如文档所述,Memory 的 finalize() 方法会自动在 malloc 内存上调用 free,因此无需担心内存泄漏。