When using func_wrap, the Caller arg can be used to access guest functions through caller.get_export. So it's possible to have something like this
linker.func_wrap("test", "call_with", |caller: Caller<'_, _>, ...| {
// I'm assuming the other arguments can be used to get a function name
match caller.get_export(func_name) {
Some(Extern::Func(f)) => f.call(caller.as_context_mut(), ..., ...).unwrap(),
_ => {}
}
})
One use case for this is when you want to have the container drive some logic, for example networking while also leaving the routing to the host. It could look something like
linker.func_wrap("test", "register_callbacks", |caller: Caller<'_, _> ,... | {...});
// This function is called by the guest to register routing rules first
// Then this is called to "deploy" the logic
linker.func_wrap("test", "receive", |caller: Caller<'_, _> | {
let msg = recv();
let (func_name, args, results) = caller.routing_rules.route(msg).unwrap();
match caller.get_export(func_name) {
Some(Extern::Func(f)) => f.call(caller.as_context_mut(), args, results).unwrap(),
_ => {}
}
})
Is this thing possible with the component model through the Guest, Host and XXImports traits ? A more structured way could be allowing a wit interface to import/require other interfaces or single functions and thus be allowed to call this from within the Host trait.
What I'm envisioning would look like this
package ....;
interface api {
require foo: func();
bar: func();
}
world baz {
import api;
}
Host side:
wasmtime::component::bindgen!({
});
use ...::api::{Host, add_to_linker};
use api::required::foo;
struct MyHost;
impl Host for MyHost {
fn bar(&mut self) {
foo();
}
}
Guest Side:
wit_bindgen::generate!();
struct MyGuest { }
impl api::Required {
fn foo() {
todo!();
}
}
The component model doesn't currently allow this kind of callback implementation; you can't call into a component instance that is already on the stack.
Some other ideas:
variant callback-actions { increment-counter, set-value(string), ... }).resource import from a common outer instance. The caller passes an instance of this resource to the callback which calls "update" methods on this resource and the caller observes the results after return.streams as a sort of rpc channel.Last updated: Dec 06 2025 at 06:05 UTC