/**
* {{ doc | default("Register a handler for " + variant_name_display + ".") }}
*
* Invokes C FFI: {{ ffi_symbol }}
*
* @param path route path
* @param handler functional interface receiving JSON request, returning JSON response
* @return 0 on success, non-zero error code on failure
*/
public int {{ method_name }}(String path, Callable handler) {
try {
// Build upcall stub from handler
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh = lookup.findVirtual(Callable.class, "handle",
MethodType.methodType(String.class, String.class));
MethodHandle boundMh = mh.bindTo(handler);
// Build C FFI signature: (context: ADDRESS, request: ADDRESS) -> ADDRESS
FunctionDescriptor upcallDesc = FunctionDescriptor.of(
ValueLayout.ADDRESS, // return: *mut c_char
ValueLayout.ADDRESS, // param 0: *mut c_void (context)
ValueLayout.ADDRESS // param 1: *const c_char (request JSON)
);
// Create adapter: (context_ptr: ADDRESS, request_ptr: ADDRESS) -> response_ptr: ADDRESS
// Marshals C pointers <-> Java strings via Arena
MethodHandle baseMh = lookup.findStatic(this.getClass(), "invokeHandlerWithMarshal",
MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, Callable.class, Arena.class)
);
MethodHandle adapter = MethodHandles.insertArguments(baseMh, 2, handler, arena);
MemorySegment upcallStub = LINKER.upcallStub(adapter, upcallDesc, arena);
// Get variant registration downcall handle
MemorySegment varAddr = LOOKUP.find("{{ ffi_symbol }}")
.or(() -> LOOKUP.find("_{{ ffi_symbol }}"))
.orElseThrow();
FunctionDescriptor varDesc = FunctionDescriptor.of(
ValueLayout.JAVA_INT, // return: int
ValueLayout.ADDRESS, // owner: *mut opaque
ValueLayout.ADDRESS, // callback: upcall stub
ValueLayout.ADDRESS // path: *const c_char
);
MethodHandle varHandle = LINKER.downcallHandle(varAddr, varDesc);
Object[] args = new Object[] {
ownerHandle, // owner
upcallStub, // callback
path // path
};
return (int) varHandle.invokeExact(args);
} catch (Throwable e) {
throw new RuntimeException("Failed to register {{ variant_name_display }} handler", e);
}
}