I am making a project which involves using JNA to pass 2D arrays from Java to C++. But I am having problems passing a 2D array. I am able to pass 1D array without problems.
Java code -
import com.sun.jna.Library;
import com.sun.jna.Native;
public class HelloWorld {
public static void main(String argv[]) {
CTest lib = CTest.ctest;
int a[][] = {{2, 3}, {2, 4}};
System.out.println(lib.helloFromC(a));
}
public interface CTest extends Library {
CTest ctest = (CTest) Native.loadLibrary("cpptest", CTest.class);
public int helloFromC(int x[][]);
}
}
C++ code
#include <stdio.h>
extern "C" __declspec(dllexport)
int helloFromC(int a[][2]) {
int i, sum = 0, j;
for(i=0;i<2;i++) {
for(j=0;j<2;j++) {
printf("%d\n",a[i][j]);
sum += a[i][j];}
}
printf("%d\n",sum);
return sum;
}
When I compile the two files, I have no error, but when I run the java file I get,
Exception in thread "main" java.lang.IllegalArgumentException: Unsupported array
argument type: class [I
at com.sun.jna.Function.convertArgument(Function.java:609)
at com.sun.jna.Function.invoke(Function.java:297)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at $Proxy0.helloFromC(Unknown Source)
at HelloWorld.main(HelloWorld.java:8)
In JNA, when you have primitive multidimensional array in both Java and C/C++ code, you need to use 1-D array in Java to map to N-D array in native code. This is because Java multidimensional array is different from native C/C++ N-D array in the sense that the memory allocation of Java N-D array for each row is NOT contiguous. So when you use this in Java
int a[][] = {{2, 3}, {2, 4}};
You're equivalently using two new
to create a 2-D array:
int[] a = new int[2];
for(int i=0; i<2; i++) {
a[i] = new int[2];
}
So in order to solve this mismatch between Java and native code problem, you have to use 1-D array in Java to simulate 2-D array, such as:
public static final int NUM_ROW = 2;
public static final int NUM_COL = 2;
int[] a = new int[NUM_ROW*NUM_COL];
For (i,j)th
element in the 1-D array a
, use
a[i*NUM_COL+j]
to access it. And you can pass this 1-D array to your JNA code
System.out.println(lib.helloFromC(a));
A detailed explanation on how multidimensional array works in JNA code is given in JNA API overview. It states how the mapping mechanism works in JNA:
To map a native multi-dimensional array, use a single-dimensional Java array with a number of elements equivalent to the full native array