JNA two-dimensional arrays

I am trying to name short ** in C using JNA.

C looks like this:

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]); } } } 
  • Passing short [] [] from JNA does not work.

  • The JNA documentation says: “To map your own multidimensional array, use a one-dimensional Java array,” but it doesn't work. Upon call

    'nativeLib.compute (new short [] {1, 2, 3, 4}, 2, 2); I get: java.lang.Error: Invalid memory access in com.sun.jna.Native.invokeVoid (native method)

  • It seems that PointerByReference is required, I tried populating the PointerByReference using a PointerByReference that contains short values, but it does not work:

     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); } 
  • I also tried:

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

But I get in[0][0] = 3184 in[0][1] = 10460 in[1][0] = 3344 in[1][1] = 10460

Does anyone have any ideas? I can't change C signature, I have to deal with this short **

Many thanks.

Decision

I am the finals! by doing this:

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

As a result:

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

Thanks a lot!

+6
source share
1 answer

JNA only processes one-dimensional arrays.

And, technically, C C. short * can be an array of 1d, 2d or 3d. You would not know if you did not know the insides. Only when reading the documentation do you know that the function expects a 2D array. All you really do is pass a pointer to the first element of the array (total length of the string * col), and then use (rowIndex * col + colIndex) to get the result. In JNA, you should only use a 1D array.

In this case, however, you have short ** , so you know that you have a 1D array of pointers, each pointer points to a 1D array of short s. In JNA, you create an array of pointers ( Pointer[] ) for the first *; each will point to the first "column" of the new row (second *).

The Invalid Memory Access error indicates that you incorrectly assigned Native memory, and gives you a strong hint of the answer: you cannot just pass a primitive array as a parameter. You must allocate its memory, either using the Memory class, or by including an array as part of Structure .

new short[] {1, 2, 3, 4} does not work here because you did not allocate memory on the side to support java memory for this array. You were on the right track with the memory allocation you used with the Memory class.

In C, short** in expects an array of pointers. Therefore, you should start by declaring an array of pointers:

 Pointer[] p = new Pointer[row]; 

Then you set the pointers for each row, allocating memory:

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

Now you can write the values ​​of the array. You can setShort() over offset columns and setShort() , but you can also write directly using Pointer.write () , e.g.

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

Then you pass p to native C for in .

+2
source

Source: https://habr.com/ru/post/1014702/


All Articles