Stream: general

Topic: Resources as callbacks?


view this post on Zulip James Mart (Feb 12 2026 at 18:49):

Hello,

Trying to understand if it's possible to use components to achieve a callback/dependency injection pattern between components.

I want to declare a resource in a callee with a particular contract, import it, and then export a function from callee that takes an instance of the resource, and then I want to execute some function on that instance:

package callee:component;

interface callbacks {
    resource some-contract {
        constructor();
        run: func(message: string);
    }
}

interface api {
    use callbacks.{some-contract};
    process: func(callback: some-contract);
}

world component {
    export api;
}

The key is, I don't want to implement the callback type in the callee, it should be implemented in a caller. I just want the callee to define:

#[allow(warnings)]
mod bindings {
    use super::Callee;
    wit_bindgen::generate!();
    export!(Callee);
}

use bindings::exports::callee::component::api;
use bindings::callee::component::callbacks;

struct Callee;

impl api::Guest for Callee {
    fn process(callback: callbacks::SomeContract) {
        callback.run("Hello, world!");
    }
}

This seems to compile, but how do I implement a caller component that can define the callback implementation that it then passes to callee:component/api::process?

view this post on Zulip Joel Dice (Feb 12 2026 at 18:58):

You won't be able to implement the caller component due to this limitation. There are unfortunately no good options for callbacks in the component model yet besides rolling your own ad-hoc version using e.g. a function table and u32 indexes into that table.

view this post on Zulip Joel Dice (Feb 12 2026 at 19:06):

Oh, and even the function table approach won't work given that recursive reentrance is disallowed currently (i.e. when the caller calls the callee and the callee tries to call back into the caller, that will trap).

With the new concurrency model, you can have the callee export an async function which can yield control to the callee, and they can talk to each other via e.g. stream<T>s, where T could be a type representing a function call and its parameters, but I think that's the best we can do at this point.

view this post on Zulip James Mart (Feb 12 2026 at 19:08):

Unfortunate answer, but thanks for the quick response!


Last updated: Feb 24 2026 at 04:36 UTC