我使用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 []定义的行。
我有这样的感觉,它不会以这种方式工作,但我希望实际上有办法。
答案 0 :(得分:0)
您没有让我们知道TDynamicAnsiCharArray
是什么,但我认为它是PAnsiChar
的动态数组:
type
TDynamicAnsiCharArray = array of PAnsiChar;
这不是二进制互操作的有效类型。
在Java方面,出于同样的原因,你不能使用String[]
作为返回值。
有很多方法可以解决这个问题。没有一个特别简单。我想也许最干净的是要求函数返回包含整个列表的单个字符串。你可能会使用像double null-terminated字符串那样粗糙的东西。或者您可以将列表序列化为JSON数组并返回该文本。对于其中任何一个选项,您只需要找到一种返回字符串的方法。
最干净的方法是让调用者分配内存。这个答案涵盖了这种技巧:How can I call a Delphi function that returns a string using JNA?
让调用者分配内存的另一种方法是使用从共享堆分配的字符串类型。显而易见的选择是Delphi中的COM BSTR
类型,WideString
。这在JNA中表示为WTypes.BSTR
。注意不要将其用作WideString
函数返回值,因为Delphi不遵循平台ABI:Why can a WideString not be used as a function return value for interop?