java - 将数组从 Delphi DLL 传递到 JNA

标签 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[] 定义的行。

我有这种感觉,这种方式根本行不通,但我希望确实有办法。

最佳答案

您没有让我们知道 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/

相关文章:

c - qsort 段错误结构

arrays - 如何从包含二进制数据的字符串中提取模式

delphi - 尝试在 Delphi 中创建 Firebird 数据库时出现 EIBInterBaseError 'unavailable database'

delphi - RestoreDC之后我需要调用TCanvas.Refresh吗?

Java - 从缓冲读取器(从套接字)读取正在暂停线程

JavaFx:运行时检查 PathTransition 的当前位置

c++ - 写在文件上,信息最终出现在控制台中

delphi - 如何在资源脚本的数据部分中使用宏?

java - Hibernate DateCreated,DateModified 列来自 DB 而不是 VM(App)

java - JToolbar 左右插入