【问题标题】:JNA two dimensional arraysJNA 二维数组
【发布时间】:2017-03-13 00:55:13
【问题描述】:

我尝试用 JNA 在 C 中调用一个 short**。

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 传递一个 short[][] 不起作用。

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

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

  • 似乎需要一个 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

非常感谢!

【问题讨论】:

  • 很高兴看到“指针数组”版本对您有用!

标签: java jna


【解决方案1】:

JNA 只处理一维数组。

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

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

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

现在,您可以编写数组值了。您可以使用 offset 和 setShort() 遍历列,但您也可以直接使用 Pointer.write() 编写,例如,

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

然后你会将p 传递给本机C 以获得in

【讨论】:

  • 关于第一种方案,调用'nativeLib.compute(new short[] { 1, 2, 3, 4 }, 2, 2);'给出一个; "线程 "main" java.lang.Error 中的异常:com.sun.jna.Native.invokeVoid(Native Method) 的内存访问无效"
  • 非常感谢您的帮助,这几乎没问题,但是使用两种更新的解决方案,结果是:in[0][0] = 1 in[0][1] = 2 in[1][0] = 3200 in[1][1] = 10525
猜你喜欢
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
  • 2019-01-23
  • 2017-01-19
  • 1970-01-01
  • 2022-01-22
相关资源
最近更新 更多