为什么 JNA 不将 char** 映射到 String[]?

Why Is JNA Not Mapping char** to String[]?

我正在尝试使用 JNA link java 程序到 dll。

在我的 C++ DLL 中,我有一个接受 char** 的函数。 JNA API 意味着应该映射到 Java 中的 String[]

据我所知 Foo(..., char** bar, ...) 应该变成 native Foo(..., String[] bar, ...)。但是,当我尝试 运行 程序时出现异常。

java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalArgumentException: class [Ljava.lang.String; is not a supported argument type (in method Foo in class DLL)
    at com.sun.jna.Native.register(Native.java:1604)
    at com.sun.jna.Native.register(Native.java:1529)
    at com.sun.jna.Native.register(Native.java:1252)
    at DLL.<clinit>(TrajParser.java:28)

如果我将 java 端的签名更改为 byte[]PointerByReference 确实 似乎允许程序启动,但我不确定如何将我的 String[] 转换为这两种类型中的任何一种。

主要原因是JNI/JNA使用原始类型。字符串实例是非原始对象(即使 classe 在 java.lang 包中),因此在内存中有一个与 C 代码不兼容的 Java 表示。有关信息,此对象的表示存储了一种结构:对 class(字符串)的引用 对内部数组表示的引用,然后该数组在内存中也有它自己的表示。

您的选择是转换字符串 from/to 字节,您需要使用字符集:

发送字符串

"My string".getBytes(StandardCharsets.UTF_8)

接收

new String(bytes,StandardCharsets.UTF_8)

事实证明,您可以创建 com.sun.jna.StringArray

而不是使用 String[]

所以它变成了 native Foo(..., StringArray bar, ...) 并调用函数你只需包装一个 String[]:

String[] array = new String[n];

DLL.Foo(..., new StringArray(array), ...);