JNA 2维数组

时间:2019-06-07 12:02:53

标签: jna

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>

任何帮助表示感谢。

1 个答案:

答案 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);