from this mailing list message:
https://mail.openjdk.java.net/pipermail/panama-dev/2022-April/016764.html
i found this link:
https://github.com/openjdk/panama-foreign/blob/foreign-jextract/doc/panama_ffi.md
which includes this example:
import jdk.incubator.foreign.Addressable;
import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.SymbolLookup;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.NativeSymbol;
import jdk.incubator.foreign.ResourceScope;
import jdk.incubator.foreign.SegmentAllocator;
import jdk.incubator.foreign.VaList;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Arrays;
import static jdk.incubator.foreign.ValueLayout.*;
public class Examples {
static CLinker LINKER = CLinker.systemCLinker();
public static void main(String[] args) throws Throwable {
strlen();
strlen_virtual();
qsort();
printf();
vprintf();
}
public static void strlen() throws Throwable {
MethodHandle strlen = LINKER.downcallHandle(
LINKER.lookup("strlen").get(),
FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
SegmentAllocator malloc = SegmentAllocator.nativeAllocator(scope);
MemorySegment hello = malloc.allocateUtf8String("Hello");
long len = (long) strlen.invoke(hello); // 5
System.out.println(len);
}
}
public static void strlen_virtual() throws Throwable {
MethodHandle strlen_virtual = LINKER.downcallHandle(
FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
SegmentAllocator malloc = SegmentAllocator.nativeAllocator(scope);
MemorySegment hello = malloc.allocateUtf8String("Hello");
long len = (long) strlen_virtual.invoke(
LINKER.lookup("strlen").get(),
hello); // 5
System.out.println(len);
}
}
static class Qsort {
static int qsortCompare(MemoryAddress addr1, MemoryAddress addr2) {
return addr1.get(JAVA_INT, 0) - addr2.get(JAVA_INT, 0);
}
}
public static void qsort() throws Throwable {
MethodHandle qsort = LINKER.downcallHandle(
LINKER.lookup("qsort").get(),
FunctionDescriptor.ofVoid(ADDRESS, JAVA_LONG, JAVA_LONG, ADDRESS)
);
FunctionDescriptor comparDesc = FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS);
MethodHandle comparHandle = MethodHandles.lookup()
.findStatic(Qsort.class, "qsortCompare",
CLinker.upcallType(comparDesc));
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
NativeSymbol comparFunc = LINKER.upcallStub(
comparHandle, comparDesc, scope);
SegmentAllocator malloc = SegmentAllocator.nativeAllocator(scope);
MemorySegment array = malloc.allocateArray(JAVA_INT, new int[] { 0, 9, 3, 4, 6, 5, 1, 8, 2, 7 });
qsort.invoke(array, 10L, 4L, comparFunc);
int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
System.out.println(Arrays.toString(sorted));
}
}
public static void printf() throws Throwable {
MethodHandle printf = LINKER.downcallHandle(
LINKER.lookup("printf").get(),
FunctionDescriptor.of(JAVA_INT, ADDRESS).asVariadic(JAVA_INT, JAVA_INT, JAVA_INT)
);
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
SegmentAllocator malloc = SegmentAllocator.nativeAllocator(scope);
MemorySegment s = malloc.allocateUtf8String("%d plus %d equals %d\n");
printf.invoke(s, 2, 2, 4);
}
}
public static void vprintf() throws Throwable {
MethodHandle vprintf = LINKER.downcallHandle(
LINKER.lookup("vprintf").get(),
FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS));
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
SegmentAllocator malloc = SegmentAllocator.nativeAllocator(scope);
MemorySegment s = malloc.allocateUtf8String("%d plus %d equals %d\n");
VaList vlist = VaList.make(builder ->
builder.addVarg(JAVA_INT, 2)
.addVarg(JAVA_INT, 2)
.addVarg(JAVA_INT, 4), scope);
vprintf.invoke(s, vlist);
}
}
}
run as: java --add-modules jdk.incubator.foreign --enable-native-access=ALL-UNNAMED Examples.java