"Pure Java" means no JNI and no hand-written C glue. Java 22's Foreign
Function & Memory API (java.lang.foreign) can both call native functions
(downcalls) and expose Java methods as C function pointers (upcalls) — which is
exactly what doomkit's callback design needs.
| FFM piece | Used for |
|---|---|
SymbolLookup.libraryLookup(...) |
open libdoomgeneric |
Linker.downcallHandle(...) |
call dg_create, dg_tick, dg_resx, ... |
Linker.upcallStub(...) |
turn onInit, onDrawFrame, ... into C function pointers |
Arena / MemorySegment |
the callback struct, the argv array, and reading the framebuffer |
- JDK 22 or newer (FFM is stable there; on 21 it was preview and a couple of method names differ).
- Build
libdoomgeneric(seebindings/README.md). - Single-file source launch (no compile step needed):
It writes
java --enable-native-access=ALL-UNNAMED \ -Djava.library.path=/path/to/lib \ Doom.java -iwad /path/to/doom1.wadframe.ppmat frame 100.--enable-native-accesssilences the restricted-method warning;-Djava.library.pathis where it looks for the native library.
- The
Arena(ARENA) is shared and never closed on purpose: it owns the upcall stubs, so it must outlive every engine callback. dg_screen_buffer()returns a zero-length segment;.reinterpret(w*h*4)gives it a real size so you can read pixels (0x00RRGGBB).- Real input: return
1fromonGetKeyand write the DOOM key code / pressed flag into the twoMemorySegmentout-parameters withset(JAVA_INT/JAVA_BYTE...).