Callback<T> represents an upcall stub, turning a Java functional interface lambda into a raw native C function pointer.
Primitive types use the same C layouts as downcalls and @Struct fields:
| Java type | Native layout |
|---|---|
int |
JAVA_INT |
long |
JAVA_LONG (always 64-bit) |
float / double / short / byte |
matching ValueLayout |
boolean |
JAVA_BYTE (C _Bool, 0/1) |
char / CChar |
JAVA_BYTE (one C char code unit) |
WChar |
platform wchar_t (JAVA_CHAR on Windows, JAVA_INT elsewhere) |
MemorySegment |
ADDRESS (pointers) |
Automatic String / array conversion is not supported for upcalls — pass
MemorySegment for pointer arguments.
import io.github.undeffineddev.ffmkit.callback.Callback;
// 1. Define a functional interface representing the callback
@FunctionalInterface
interface Compare {
int compare(int a, int b);
}
public class Main {
public static void main(String[] args) {
// 2. Create the Callback stub
try (Callback<Compare> callback = Callback.of((a, b) -> a - b, Compare.class)) {
// Pass this pointer (MemorySegment) to native functions like qsort
java.lang.foreign.MemorySegment nativePtr = callback.segment();
// ...
} // the callback upcall stub is unregistered and freed when closed
}
}See NativeTypes.md for the full type table.
CChar and WChar callbacks are adapted through the same registered mappers used by
downcalls and structs, so callback methods can retain their native C character types:
@FunctionalInterface
interface TransformChar {
CChar apply(CChar value);
}
try (Callback<TransformChar> callback = Callback.of(value -> value, TransformChar.class)) {
// Pass callback.segment() as a native function pointer.
}