Pregunta

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)
¿Fue útil?

Solución

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top