将数组从Delphi DLL传递到JNA

时间:2014-11-11 11:35:46

标签: java arrays delphi dll jna

我使用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 []定义的行。

我有这样的感觉,它不会以这种方式工作,但我希望实际上有办法。

1 个答案:

答案 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?