JNA二维数组

时间:2017-02-04 16:04:45

标签: java jna

我尝试使用JNA在C中调用短**。

C看起来像这样:

void compute(short** in, int row, int col) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf("in[%d][%d] = %d\n", i,j, in[i][j]);
        }
    }
}
  • 从JNA传递短[] []不起作用。

  • JNA文档说“要映射本机多维数组,请使用一维Java数组”但它不起作用。致电时

    'nativeLib.compute(new short [] {1,2,3,4},2,2); 我得到:java.lang.Error:com.sun.jna.Native.invokeVoid(本机方法)无效的内存访问

  • 似乎需要PointerByReference,我试图用PointerByReference填充PointerByReference,其中包含短值,但它不起作用:

    Pointer pointerOfArray = new Memory(row * col * Native.getNativeSize(Short.TYPE));
    for(int i=0;i<row;i++) {
    
        Pointer pointer = new Memory(col * Native.getNativeSize(Short.TYPE));
        for(int j=0;j<col;j++) {
            pointer.setShort(j*Native.getNativeSize(Short.TYPE), in[i][j]);
        }
        pointerOfArray.setPointer(i*row*Native.getNativeSize(Short.TYPE), pointer);
    }
    
  • 我也尝试过:

        Pointer pointer = new Memory(4*Short.SIZE);
    
    Pointer pointer1 = new Memory(2*Short.SIZE);
    pointer1.setShort(0,(short)1);
    pointer1.setShort(Short.SIZE,(short)2);
    
    Pointer pointer2 = new Memory(2*Short.SIZE);
    pointer2.setShort(0,(short)3);
    pointer2.setShort(Short.SIZE,(short)4);
    
    pointer.setPointer(0, pointer1);
    pointer.setPointer(2*Short.SIZE, pointer2);
    
    nativeLib.compute(new PointerByReference(pointer), 2,2);
    

但我得到in[0][0] = 3184 in[0][1] = 10460 in[1][0] = 3344 in[1][1] = 10460

有没有人有想法?我无法改变C签名,我必须处理这个简短的**

非常感谢。

解决方案

我终于成功了!这样做:

        short[][] in = {
            {1,2,3},
            {4,5,6},
    };

    Pointer[] data = new Pointer[in.length];
    for(int i=0;i<in.length;i++) {
        data[i] = new Memory(2*Short.SIZE);
        data[i].write(0, in[i], 0,in[0].length);
    }

    nativeLib.compute(data, in.length,in[0].length);

结果:

in[0][0] = 1
in[0][1] = 2
in[0][2] = 3
in[1][0] = 4
in[1][1] = 5
in[1][2] = 6

非常感谢!

1 个答案:

答案 0 :(得分:2)

JNA只处理单维数组。

而且,从技术上讲,C也是如此。short *可以是1d,2d或3d数组。除非你知道内部,否则你不会知道。只有通过阅读文档才能知道该函数需要2D数组。您所做的只是将指针传递给数组的第一个元素(总长度行* col),然后使用(rowIndex * col + colIndex)来获取结果。在JNA中,您只需使用一维数组进行匹配。

但是,在这种情况下,你有一个short **,所以你知道你有一个指针数组,每个指针都指向short的一维数组。在JNA中,您为第一个*创建一个指针数组(Pointer[]);每个都将指向新行的第一个“列”(第二个*)。

Invalid Memory Access错误表示您没有正确分配本机内存,并给出了强烈的答案提示:您不能简单地将原始数组作为参数传递。您必须使用Memory类或将数组作为Structure的一部分来分配其内存。

new short[] {1, 2, 3, 4}在这里不起作用,因为你没有分配本机内存以支持该数组的java内存。通过使用Memory类进行的内存分配,您处于正确的轨道上。

在C中,short** in期待一个指针数组。所以你应该从声明一个指针数组开始:

Pointer[] p = new Pointer[row];

然后你将为每一行设置指针,分配内存:

p[0] = new Memory(col * Native.getNativeSize(Short.TYPE));
p[1] = new Memory(col * Native.getNativeSize(Short.TYPE));

现在,您可以编写数组值。您可以使用偏移量setShort()迭代列,但您也可以使用Pointer.write()直接编写,例如,

p[0].write(0, new short[] {1, 2}, 0, 2);
p[1].write(0, new short[] {3, 4}, 0, 2);

然后,您将p传递给in的原生C。