Java JNA 无效内存访问

Java JNA Invalid Memory Access

我有一个用Delphi写的DLL(没有源代码,只有API)。这是我尝试使用 JNA(版本 5.4.0)

通过 Java 调用的 DLL 函数

下面显示了我的 Java 代码的样子。

public interface FPrintDLL extends StdCallLibrary {
    FPrintDLL INSTANCE = Native.load("FPrintDLL", FPrintDLL.class);
    int OPEN_TCPIP(WString ipAddress, int port, int deviceIndex, WString serialKey);
}

public static void main(String[] args) {
    FPrintDLL fPrintDLL = FPrintDLL.INSTANCE;
    WString ipAddress = new WString("192.170.1.3");
    WString serialKey = new WString("12345678");
    int deviceIndex = 4004;
    int port = 9100;

    int connectResult = fPrintDLL.OPEN_TCPIP(ipAddress, port, deviceIndex, serialKey); // Line 81
}

一切正常,问题是我收到以下异常,

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:426)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy0.OPEN_TCPIP(Unknown Source)
at HelloJNA.main(HelloJNA.java:81)

根据异常日志,问题的发生是因为整数。根据方法签名,它不使用任何 pointers/references。所以我不确定到底是什么问题。

注意 - 我设法在相同条件下成功运行这个功能(列出了OS、JAVA、DLL架构下面)使用以下 C# 代码,

[DllImport(FPRINT_DLL, CallingConvention = CallingConvention.StdCall)]
public static extern int OPEN_TCPIP([MarshalAs(UnmanagedType.BStr)] string ipAddress,
        int tcpPort,
        int deviceIndex,
        [MarshalAs(UnmanagedType.BStr)] string serialKey);

我提到这个是为了确认 OPEN_TCPIP 的给定 API 是正确的。现在我想在 Java 和 DLL 之间进行直接交互。 (不使用某种包装器 class)

DLL 是一个 32 位 DLL,我正在 32 位 JVM、Windows10 64 位上尝试它。 仅供参考,我尝试了以下来源(列出的几个)但无法解决这个问题。

DLL issues and Invalid Memory Access

Java Native Access code Error: “Invalid memory access”

Function call returns java.lang.Error: Invalid memory access

JNA: java.lang.Error: Invalid memory access

Java use JNA call dll error:Invalid memory access(所有必需的 DLL 都在同一目录中)

有人知道如何解决这个问题吗?

方法签名需要 BSTR,这需要在 C 端分配内存。您传递的 WString 导致无效内存访问。

像这样为 BSTR 参数分配内存:

BSTR ipAddress = OleAuto.INSTANCE.SysAllocString("192.170.1.3");
BSTR serialKey = OleAuto.INSTANCE.SysAllocString("12345678");

完成 BSTR 后,您必须释放内存:

OleAuto.INSTANCE.SysFreeString(ipAddress);
OleAuto.INSTANCE.SysFreeString(serialKey);