Stream: wit-bindgen

Topic: external export implementations


view this post on Zulip Gabriel Hansson (Aug 26 2023 at 20:09):

Hii!

I'm playing around with a toy web browser in which a fictitious Web API is defined in WIT. Let's call that interface wawi :3

A tiny wit world so far been created that defines a print(message: string) import and main() export that works well with wit_bindgen::generate! for the guest implementation and wasmtime::component::bindgen! for the host implementation.

Thing is, it seems like the Guest implementation has to be done in the module where the generate!() invocation is made. But I'm only interested in it generating the imports, and then have an external crate implement the exports. Something that might be similar to this:

// crate `wawi`:
pub use wawi_internal::wawi;
pub use wawi_internal::Guest as App;
mod wawi_internal {
    wit_bindgen::generate!({
        path: "../../wawi-wit",
        world: "wawi",
    });
}
// wawi dependant crate: `webb_app`
use ::wawi::{wawi, App};

struct MyWebApp;

impl App for MyWebApp {
    fn main() {
        wawi::dom::print::println("Hello, wawi!");
    }
}

As you probably know, this won't work since the extern "C" main() is expanded by generate!. But I was able to work around this by moving the expanded code over to webb_app, without it explicitly depending on wit-bindgen:

use ::wawi::{wawi, App};

struct MyWebApp;

impl App for MyWebApp {
    fn main() {
        wawi::dom::print::println("Hello, Wawi!");
    }
}

const _: () = {
    #[doc(hidden)]
    #[export_name = "main"]
    #[allow(non_snake_case)]
    unsafe extern "C" fn __export_main() {
        #[allow(unused_imports)]
        use ::wawi::runtime::{alloc, String, Vec};
        #[cfg(target_arch = "wasm32")]
        ::wawi::runtime::run_ctors_once();
        MyWebApp::main()
    }
};
// crate `wawi`:
pub use wawi_internal::wawi;
pub use wawi_internal::Guest as App;
pub mod runtime {
    #[cfg(target_arch = "wasm32")]
    pub use wit_bindgen::rt::{alloc, run_ctors_once, string::String, vec::Vec};
}

// ...

Clearly, this won't scale as is, hence the following questions :see_no_evil:

Would love to hear your input/tips on resources I could look into.

Thanks :blush:

view this post on Zulip Alex Crichton (Aug 28 2023 at 14:14):

For imports/exports I think that may be fixable by adding more features to the macro. For example in Wasmtime we have the ability to generate WASI types in one crate and then use those from other crates. That feature hasn't been ported to the guest Rust macro yet though, so it'd take some work.

For having a trait that a different crate implements I think the short answer is that it's basically not great right now. I'd recommend looking into what cargo component generates since that's solving a similar problem, although its solution may be derivative of the fact that it controls more of the compilation process than a simpler crate dependency. More-or-less I think we're still iterating on this space of how to get the user to implement a set of exported functions and have that registered with WIT exports

view this post on Zulip Lloyd Fournier (Sep 22 2023 at 03:09):

this also affects me so I made an issue: https://github.com/bytecodealliance/wit-bindgen/issues/674

See discussion here: https://bytecodealliance.zulipchat.com/#narrow/stream/327223-wit-bindgen/topic/external.20export.20implementations/near/387677837 I also want this feature. It kind of used to e...

Last updated: Nov 22 2024 at 16:03 UTC