I have a native .so
library that has the following function:
void foo(void* handle);
It works well in C#:
[DllImport("library.so", CallingConvention = (CallingConvention) 3)]
private static extern void foo(ref IntPtr handle);
// ...
IntPtr handle = IntPtr.Zero;
foo(ref handle);
However, I cannot implement it in Java 22 using FFM API:
var LINKER = Linker.nativeLinker();
var SYM_LOOKUP = SymbolLookup.loaderLookup().or(LINKER.defaultLookup());
var FOO = LINKER.downcallHandle(SYM_LOOKUP.find("foo").orElseThrow(), FunctionDescriptor.ofVoid(ADDRESS));
var handle = Arena.global().allocate(ValueLayout.ADDRESS); // is this correct?
FOO.invokeExact(handle);
For some reason, I get std::bad_array_new_length
in the native code (unfortunately, I don't have source code of the native library).
In JNA, there is com.sun.jna.ptr.IntByReference
, is there something similar in FFM API?
I found the error. Actually I had 2 native methods:
void initHandle(void* handle);
void useHandle(void* handle);
and I need to initialize the handle then use it. I was doing this:
var handle = Arena.global().allocate(ValueLayout.ADDRESS);
INIT_HANDLE.invokeExact(handle);
USE_HANDLE.invokeExact(handle);
It turns out that I had to pass the handle differently in second function:
var handle = Arena.global().allocate(ValueLayout.ADDRESS);
INIT_HANDLE.invokeExact(handle);
USE_HANDLE.invokeExact(handle.get(ValueLayout.ADDRESS, 0));