我正在尝试使用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[]
转换成上述两种类型。
答案 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), ...);