JNA 2维数组
我的C函数是
void func(void** bufs, int numBufs);
Tye C代码需要一个指向字节数组的指针数组。 func()
知道每个字节数组的长度,并用数据填充它们。
JNA签名是什么?
我已经解决了这个看似简单的问题两天了,但是还没有破解。
在Java方面,我有DirectBuffer bufs[]
,目的是让C函数用数据填充bufs[]
。
我曾希望我可以将JNA签名声明为
public static native boolean func(Pointer[] bufs, int numBufs);
,然后构造一个Java指针数组,每个指针为new Pointer(db.address());
但是当我可以构造Pointer的java数组时,我得到了错误:
java.lang.IllegalArgumentException: class [Lcom.sun.jna.Pointer; is not a supported argument type (in method func in class SomeLib)
我经过长时间的尝试,却一无所获。我查看了StackOver流上的所有JNA示例,但都不太合适。
我正在通过Maven使用JNA
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.3.1</version>
</dependency>
任何帮助表示感谢。
答案 0 :(得分:1)
您已经关闭。不幸的是,非原始数组到C的映射仅以一种方式起作用...您可以将检索到的内存映射到Java数组,而不能将Java数组发送到C(原始除外)。
此限制的原因是在C语言中,数组是连续的内存块。要访问数组的第二个元素,只需偏移等于第一个元素大小的字节数即可。但是,传递给C函数的参数只是指向数组开头的指针。
因此,您对func()
的映射应使用Pointer
作为数组参数。
您没有描述如何构造Pointer[]
数组,但是使用new Pointer()
调用分配每个数组将产生分散在本机内存中而不是连续的指针。
基本上,有两种方法可以确保您拥有连续的内存,具体取决于所需的抽象级别。
一种低层方法是创建一个Memory
对象,为您的Pointer
数组(可能是new Memory(Native.POINTER_SIZE * numBufs)
)分配足够的空间,然后使用setPointer()
和适当的倍数的Native.POINTER_SIZE
偏移量将数组映射到Memory
对象。然后将Memory
对象传递给C函数。
更高级的方法是将指针包装在JNA Structure
中,使用Structure.toArray()
方法为您完成连续的数组分配。所以你可以这样:
public class Foo extends Structure {
public Pointer bar;
}
然后创建数组:
Foo[] array = (Foo[]) new Foo().toArray(numBufs);
这时,您具有一个(连续的)本地内存数组,映射到JNA的Pointer
类型。现在,您只需要将这些Pointer-to-pointers分配给数据附加的指针:
for (int i = 0; i < numBufs; i++) {
// Assign Pointer to corresponding DirectBuffer
array[i].bar = bufs[i];
}
然后,您应该可以通过传递第一个元素的指针将Array传递给C:
func(array[0].bar, numBufs);
// or equivalently
func(array[0].getPointer(), numBufs);