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

时间:2018-09-25 11:15:08

标签: java jna

我正在尝试使用JNA将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[]转换成上述两种类型。

2 个答案:

答案 0 :(得分:1)

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

您的选项是将字符串转换为字节,您需要使用字符集:

发送字符串

"My string".getBytes(StandardCharsets.UTF_8)

接收

new String(bytes,StandardCharsets.UTF_8)

答案 1 :(得分:0)

结果不是使用String[],而是创建com.sun.jna.StringArray

因此它变成native Foo(..., StringArray bar, ...)并只需包装String[]即可调用该函数:

String[] array = new String[n];

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