javac#c++jnajava-ffm

JNA's IntByReference in Java Foreign Function & Memory API


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?


Solution

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