I trying to downcall C code from Java, using Foreign Linker API. The target is to print 2D array (matrix) from C. But i can't understand how can i send int[][] to C from Java.
C code:
#include "library.h"
#include <iostream>
extern "C"
{
void printMatrix(int **matrix, int width, int height) {
for (int i = 0; i < width; ++i) {
printArray(matrix[i], height);
std::cout << std::endl;
}
}
void printArray(int *array, int width) {
for (int j = 0; j < width; ++j) {
std::cout << array[j] << " ";
}
}
};
I understand that int[][] in memory is "array of links to arrays", so i try to send this as MemoryAddress of long[] where i put addresses of int[]'s
public static void main(String[] args) throws Throwable {
System.loadLibrary("test_matrix");
MethodHandle handle = CLinker.getInstance().downcallHandle(
SymbolLookup.loaderLookup().lookup("printMatrix").orElseThrow(),
MethodType.methodType(void.class, MemoryAddress.class, int.class, int.class),
FunctionDescriptor.ofVoid(CLinker.C_POINTER, CLinker.C_INT)
);
int[][] arr = {{1, 2}, {2, 3}, {3, 4}};
try (ResourceScope rs = ResourceScope.newConfinedScope()) {
long[] memories = new long[arr.length];
for (int i = 0; i < arr.length; ++i) {
MemorySegment ms = allocateArray(arr[i], rs);
memories[i] = ms.address().toRawLongValue();
}
MemorySegment ms = MemorySegment.allocateNative(8L * memories.length, rs);
ms.copyFrom(MemorySegment.ofArray(memories));
handle.invokeExact(ms.address(), arr.length, 2);
}
}
private static MemorySegment allocateArray(int[] array, ResourceScope rs) {
MemorySegment ms = MemorySegment.allocateNative(4L * array.length, rs);
ms.copyFrom(MemorySegment.ofArray(array));
return ms;
}
I been able to call printArray function, but when i try to call printMatrix i got
exception:
Exception in thread "main" java.lang.IllegalArgumentException: Arity mismatch: (MemoryAddress,int,int)void != (b64[abi/kind=POINTER]b32[abi/kind=INT])v
at jdk.incubator.foreign/jdk.internal.foreign.abi.SharedUtils.checkFunctionTypes(SharedUtils.java:247)
at jdk.incubator.foreign/jdk.internal.foreign.abi.x64.sysv.CallArranger.getBindings(CallArranger.java:89)
at jdk.incubator.foreign/jdk.internal.foreign.abi.x64.sysv.CallArranger.arrangeDowncall(CallArranger.java:125)
at jdk.incubator.foreign/jdk.internal.foreign.abi.x64.sysv.SysVx64Linker.downcallHandle(SysVx64Linker.java:90)
at jdk.incubator.foreign/jdk.internal.foreign.AbstractCLinker.downcallHandle(AbstractCLinker.java:44)
at ru.semperante.tests.MainClass.main(MainClass.java:68)