我正在使用 Java JNA 库来调用我创建的 Delphi DLL。我使用的 Delphi 函数返回一个类型,即 PAnsiChar 数组。我遇到的问题是,当我尝试在 Java 中调用该函数时,它给了我一个 java.lang.Error: Invalid memory access
。
我的 Delphi 代码在这里:
function doTest(inputStatement: PAnsiChar): TDynamicAnsiCharArray; stdcall;
begin
SetLength(result, 3);
result[0] := 'Line 1';
result[1] := 'Line 2';
result[2] := 'Line 3';
end;
我的Java代码在这里:
public interface CLib extends StdCallLibrary {
CLib INSTANCE = (CLib) Native.loadLibrary("DatabaseLibrary", CLib.class);
public String[] doTest(String input);
}
public Main() {
String[] dllOut = CLib.INSTANCE.doTest("Test?");
for(int i = 0; i < dllOut.length; i++){
System.out.println(dllOut[i]);
}
}
完整的 Java 错误在这里:
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invoke(Function.java:430)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.doTest(Unknown Source)
at Main.<init>(Main.java:17)
at Main.main(Main.java:25)
第 17 行是包含 String[] 定义的行。
我有这种感觉,这种方式根本行不通,但我希望确实有办法。
最佳答案
您没有让我们知道 TDynamicAnsiCharArray
是什么,但我认为它是 PAnsiChar
的动态数组:
type
TDynamicAnsiCharArray = array of PAnsiChar;
这不是二进制互操作的有效类型。
在 Java 方面,出于同样的原因,您不能使用 String[]
作为返回值。
有很多方法可以解决这个问题。没有一个是特别简单的。我认为也许最干净的方法是要求函数返回包含整个列表的单个字符串。您可能会使用一些粗略的东西,例如双空终止字符串。或者,您可以将列表序列化为 JSON 数组并返回该文本。对于这些选项中的任何一个,您只需要找到一种返回字符串的方法。
最简洁的方法是让调用者分配内存。这个答案涵盖了该技术:How can I call a Delphi function that returns a string using JNA?
让调用者分配内存的另一种方法是使用从共享堆分配的字符串类型。显而易见的选择是 COM BSTR
类型,Delphi 中的 WideString
。这在 JNA 中表示为 WTypes.BSTR
。但请注意不要将其用作 WideString
函数返回值,因为 Delphi 不遵循平台 ABI: Why can a WideString not be used as a function return value for interop?
关于java - 将数组从 Delphi DLL 传递到 JNA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26863944/