JNA 二维数组
JNA two dimensional arrays
我尝试用 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 文档说 "To map a native multi-dimensional array, use a single-dimensional Java array" 但它不起作用。调用时
'nativeLib.compute(新短[] { 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
非常感谢!
JNA 仅处理一维数组。
而且,从技术上讲,C 也是如此。short *
可以是 1d、2d 或 3d 数组。除非你知道内部结构,否则你不会知道。只有阅读文档,您才知道该函数需要一个二维数组。您真正要做的就是将指针传递给数组的第一个元素(总长度 row*col),然后使用 (rowIndex * col + colIndex) 获取结果。在 JNA 中,您只需使用一维数组进行匹配。
然而,在这种情况下,您有一个 short **
,因此您知道您有一个一维指针数组,每个指针指向一个 short
的一维数组。在 JNA 中,您为第一个 * 创建一个指针数组 (Pointer[]
);每个都将指向新行的第一个 "column"(第二个 *)。
Invalid Memory Access
错误表明您没有正确分配本机内存,并给您一个强烈的答案提示:您不能简单地将原始数组作为参数传递。您必须分配其内存,方法是使用 Memory
class 或将数组作为 Structure
.
的一部分
new short[] {1, 2, 3, 4}
在这里不起作用,因为您还没有分配 native-side 内存来支持该数组的 java 内存。您使用 Memory
class 进行的内存分配是正确的。
在 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
传递给 in
的本机 C。
我尝试用 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 文档说 "To map a native multi-dimensional array, use a single-dimensional Java array" 但它不起作用。调用时
'nativeLib.compute(新短[] { 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
非常感谢!
JNA 仅处理一维数组。
而且,从技术上讲,C 也是如此。short *
可以是 1d、2d 或 3d 数组。除非你知道内部结构,否则你不会知道。只有阅读文档,您才知道该函数需要一个二维数组。您真正要做的就是将指针传递给数组的第一个元素(总长度 row*col),然后使用 (rowIndex * col + colIndex) 获取结果。在 JNA 中,您只需使用一维数组进行匹配。
然而,在这种情况下,您有一个 short **
,因此您知道您有一个一维指针数组,每个指针指向一个 short
的一维数组。在 JNA 中,您为第一个 * 创建一个指针数组 (Pointer[]
);每个都将指向新行的第一个 "column"(第二个 *)。
Invalid Memory Access
错误表明您没有正确分配本机内存,并给您一个强烈的答案提示:您不能简单地将原始数组作为参数传递。您必须分配其内存,方法是使用 Memory
class 或将数组作为 Structure
.
new short[] {1, 2, 3, 4}
在这里不起作用,因为您还没有分配 native-side 内存来支持该数组的 java 内存。您使用 Memory
class 进行的内存分配是正确的。
在 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
传递给 in
的本机 C。