alef 0.77.0

Opinionated polyglot binding generator for Rust libraries
Documentation
    /**
     * {{ doc | default("Register a handler for " + variant_name_display + ".") }}
     *
     * Invokes C FFI: {{ ffi_symbol }}
     *
     * @param handler functional interface receiving JSON request, returning JSON response
     * @return 0 on success, non-zero error code on failure
     */
    public int {{ method_name }}({{ signature_params }}{% if signature_params %}, {% endif %}Callable handler) {
        try (var ownerLease = borrowOwnerHandle();
             var callArena = Arena.ofConfined();
             var nativeResources = new ServiceResources(){% if lease_resources %}; {{ lease_resources }}{% endif %}) {
{{ metadata_setup }}
            MethodHandles.Lookup lookup = MethodHandles.lookup();
            MethodHandle baseMh = lookup.findStatic({{ class_name }}.class, "invokeHandlerWithMarshal",
                MethodType.methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class, Callable.class, Arena.class)
            );
            MethodHandle adapter = MethodHandles.insertArguments(baseMh, 2, handler, arena);
            FunctionDescriptor upcallDesc = FunctionDescriptor.of(
                ValueLayout.ADDRESS,
                ValueLayout.ADDRESS,
                ValueLayout.ADDRESS
            );
            MemorySegment upcallStub = LINKER.upcallStub(adapter, upcallDesc, arena);
            MethodHandle responseFree = lookup.findStatic({{ class_name }}.class, "freeHandlerResponse",
                MethodType.methodType(void.class, MemorySegment.class));
            MemorySegment responseFreeStub = LINKER.upcallStub(responseFree,
                FunctionDescriptor.ofVoid(ValueLayout.ADDRESS), arena);
            MemorySegment varAddr = LOOKUP.find("{{ ffi_symbol }}")
                .or(() -> LOOKUP.find("_{{ ffi_symbol }}"))
                .orElseThrow();
            FunctionDescriptor varDesc = FunctionDescriptor.of(
                ValueLayout.JAVA_INT,
                ValueLayout.JAVA_LONG,
                ValueLayout.ADDRESS,
                ValueLayout.ADDRESS,
                ValueLayout.ADDRESS
{% for layout in descriptor_layouts %}
                , {{ layout.0 }}    // {{ layout.1 }} param
{% endfor %}            );
            MethodHandle varHandle = LINKER.downcallHandle(varAddr, varDesc);
            return (int) varHandle.invokeWithArguments(
                ownerLease.handle(),
                upcallStub,
                responseFreeStub,
                MemorySegment.NULL
{% for arg in invoke_args %}
                , {{ arg }}
{% endfor %}            );
        } catch (Throwable e) {
            throw new RuntimeException("Failed to register {{ variant_name_display }} handler", e);
        }
    }