Stream: wasmtime

Topic: Accessing Guest functions from Host functions in Components


view this post on Zulip Antoine Lavandier (Oct 14 2025 at 10:19):

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.

view this post on Zulip Antoine Lavandier (Oct 14 2025 at 11:11):

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!();
  }
}

view this post on Zulip Lann Martin (Oct 14 2025 at 12:33):

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.

view this post on Zulip Lann Martin (Oct 14 2025 at 12:45):

Some other ideas:


Last updated: Dec 06 2025 at 06:05 UTC