Comments on: Java Foreign Function & Memory API (FFM API) https://www.happycoders.eu/java/foreign-function-memory-api/ Fri, 29 Nov 2024 08:05:34 +0000 hourly 1 By: Sven Woltmann https://www.happycoders.eu/java/foreign-function-memory-api/#comment-27790 Sun, 19 May 2024 09:26:04 +0000 https://www.happycoders.eu/?p=39198#comment-27790 In reply to Bob.

Hello Bob,

you can do that as in the following example, where I use the strtof function that takes as second parameter a pointer to a pointer:

SymbolLookup stdlib = Linker.nativeLinker().defaultLookup();

MethodHandle strtof =
    Linker.nativeLinker()
        .downcallHandle(
            stdlib.find("strtof").orElseThrow(),
            FunctionDescriptor.of(
                ValueLayout.JAVA_FLOAT, ValueLayout.ADDRESS, ValueLayout.ADDRESS));

try (Arena offHeap = Arena.ofConfined()) {
  MemorySegment nptr = offHeap.allocateFrom("3.1415 equals Pi");
  MemorySegment endptr = offHeap.allocate(ValueLayout.ADDRESS);

  float result = (float) strtof.invoke(nptr, endptr);
  System.out.println("result = " + result);

  MemorySegment end = endptr.get(ValueLayout.ADDRESS, 0);
  String endString = end.reinterpret(nptr.byteSize()).getString(0);
  System.out.println("endString = " + endString);
}

The code prints the following:

result = 3.1415
endString =  equals Pi

The pointer pointer endptr is of type ValueLayout.ADDRESS. And what you get out of it, the pointer end, is again of type ValueLayout.ADDRESS. And then you can get the actual end string out of that end pointer. And for that, you need to reinterpret the memory segment, so the getString() function can read every character up to the termination character.

I used nptr.byteSize() as the new size as the output string could not be longer than the input string. If you have no idea how long the result string is, you could also use Long.MAX_VALUE.

]]>
By: Sven Woltmann https://www.happycoders.eu/java/foreign-function-memory-api/#comment-27689 Sat, 18 May 2024 15:31:51 +0000 https://www.happycoders.eu/?p=39198#comment-27689 In reply to mike.

Dear Mike,

Re 1) On a 32-bit-machine, you would have to use JAVA_INT. JEP 454 (https://openjdk.org/jeps/454) specifies: "developers are responsible for obtaining suitable layout definitions for C types. [...] We expect that in practice such layouts will be mechanically generated by tools that are specific to target native platforms."

Re 2) FFM is not aware of name mangling. You have to mark your methods as `extern "C"`, then the compiler won't rename them.

Best wishes
Sven

]]>
By: Bob https://www.happycoders.eu/java/foreign-function-memory-api/#comment-27035 Thu, 09 May 2024 13:25:07 +0000 https://www.happycoders.eu/?p=39198#comment-27035 How can I interact with pointer pointers?

Like I have this C code:

Point* out;

Point* input = ...

int result = doSomething(in, &out);

result = workWith(out)

How can I do this from FFM in java?

]]>
By: mike https://www.happycoders.eu/java/foreign-function-memory-api/#comment-24974 Sat, 30 Mar 2024 21:05:15 +0000 https://www.happycoders.eu/?p=39198#comment-24974 1. You use "ValueLayout.JAVA_LONG – for the number of elements in the array", but that value is in fact `size_t` and can be either 32- or 64-bit. What must be written if the underlying architecture is 32-bit?
Has the problem of writing to both 32-bit and 64-bit architectures been approached?

2. There are C functions and C++ functions, for C++ functions some name mangling scheme is used, and that scheme is, in the general case, compiler-dependent. On the other hand, g++ is everywhere or almost everywhere. Is Java aware of C++ name mangling? Can it work with C++ objects (e.g. std::string)?

]]>