{%- if doc %}
{{ doc }}{%- endif %}
    public func {{ variant_name }}(_ handler: @escaping (String) -> String{% if signature_params %}, {% for param in signature_params %}{{ param.name }}: {{ param.swift_type }}{{ "," if not loop.last else "" }}{% endfor %}{% endif %}) throws {
        // Box the handler and retain it; the box pointer is passed to the
        // C layer as the trampoline context and released in deinit.
        let handlerBox = HandlerBox(handler)
        let contextPtr = Unmanaged.passRetained(handlerBox).toOpaque()
        handlerBoxes.append(contextPtr)

        // Create a C-compatible callback wrapper
        let trampolineFunc: @convention(c) (UnsafeMutableRawPointer?, UnsafePointer<UInt8>?, Int) -> UnsafeMutablePointer<UInt8>? = { contextPtr, requestPtr, requestLen in
            guard let contextPtr = contextPtr else { return nil }
            guard let requestPtr = requestPtr else { return nil }

            // Recover the boxed handler closure from the context pointer
            let handlerBox = Unmanaged<HandlerBox>.fromOpaque(contextPtr).takeUnretainedValue()
            let requestData = Data(bytes: requestPtr, count: requestLen)
            let requestJSON = String(data: requestData, encoding: .utf8) ?? ""
            let responseJSON = handlerBox.handler(requestJSON)

            // Allocate response string on heap (Rust side frees via extern "C" { fn free })
            let responseBytes = responseJSON.utf8CString
            let responsePtr = UnsafeMutablePointer<UInt8>.allocate(capacity: responseBytes.count)
            for (i, byte) in responseBytes.enumerated() {
                responsePtr[i] = UInt8(bitPattern: byte)
            }
            return responsePtr
        }

        guard let inner = inner else { throw ServiceError.invalidHandle }

        // Call the C function via @_silgen_name. The callback registration is defined
        // OUTSIDE the swift-bridge module as a plain extern "C" function. swift-bridge
        // hides the wrapper's raw pointer behind an `internal` field, so call through
        // the alef-emitted `RustBridge.{{ service_camel }}RawPtr` shim which returns
        // the App address as a `usize` we can reconstitute into an OpaquePointer.
        let rawAddr = RustBridge.{{ service_camel }}RawPtr(inner)
        var innerPtr = OpaquePointer(bitPattern: rawAddr)!
        let result = _{{ service_snake }}_{{ base_method_name }}_via_callback(
            &innerPtr,
            {% for arg in wrapper_call_args %}{{ arg }},
            {% endfor %}contextPtr,
            trampolineFunc
        )
        guard result == 0 else { throw ServiceError.registrationFailed }
    }
