Stream: wasmtime

Topic: ✔ _


view this post on Zulip Nerdachse (Jul 12 2024 at 11:02):

Hello! This is my first post on Zulip, I hope I am doing it right. Thanks for all your hard work everyone!

I am currently diving into cargo component and wasmtime to evaluate their use for a (simple) plugin system in Rust.

I have the following wasm-component created via cargo component:

Cargo.toml

[package]
name = "test-plugin-lib"
version = "0.1.0"
edition = "2021"

[dependencies]
wit-bindgen-rt = { version = "0.26.0", features = ["bitflags"] }

[lib]
crate-type = ["cdylib"]

[profile.release]
codegen-units = 1
opt-level = "s"
debug = false
strip = true
lto = true

[package.metadata.component]
package = "component:test-plugin-lib"

[package.metadata.component.dependencies]

wit/world.wit

package nerdachse:test-plugin-lib@0.1.0;

interface register {
  init: func() -> string;
}

interface info {
    info: func() -> plugininfo;

    record plugininfo {
      name: string,
      version: string,
      permissions: list<string>,
    }
}

world plugin {
    export info;
    export register;
}

lib.rs

#[allow(warnings)]
mod bindings;
use bindings::exports::nerdachse::test_plugin_lib::info::Guest as InfoGuest;
use bindings::exports::nerdachse::test_plugin_lib::info::Plugininfo;
use bindings::exports::nerdachse::test_plugin_lib::register::Guest as RegisterGuest;
//use bindings::Guest as WorldGuest;

struct Component;

impl RegisterGuest for Component {
    fn init() -> String {
        "I want moar!".to_owned()
    }
}

impl InfoGuest for Component {
    fn info() -> Plugininfo {
        Plugininfo {
            name: "testplugin".to_owned(),
            version: "0.0.1".to_owned(),
            permissions: vec!["ladida".to_owned(), "permission2".to_string()],
        }
    }
}

bindings::export!(Component with_types_in bindings);

And a host:

Cargo.toml

[package]
name = "simple-host"
version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = "1.0.86"
wasmtime = "22.0.0"
wasmtime-wasi = "22.0.0"

Now I want to call the info function for all plugins in a path:

    let mut plugin_instances: Vec<(PathBuf, wasmtime::component::Instance)> = vec![];

    let mut store = wasmtime::Store::new(&engine, host);
    for (path, component) in plugins {
        match linker.instantiate(&mut store, &component) {
            Ok(instance) => {
                plugin_instances.push((path, instance));
            }
            Err(e) => {
                eprintln!("Failed to instantiate plugin@{path:?}: {e:?}");
            }
        }
    }
    for (path, plugin) in plugin_instances {
        let info_func = {
            let mut exports: wasmtime::component::Exports = plugin.exports(&mut store);
            let mut register = exports
                .instance("info")
                .expect(&format!("plugin@{:?} to have info instance", path));
            match register.typed_func::<(), (String,)>("info") {
                Ok(info) => info,
                Err(e) => {
                    eprintln!("plugin@{:?} does not have an info function: {}!", path, e);
                    continue;
                }
            }
        };

Running this gives me the error:

Running `target/release/simple-host`
Found wasm plugin @ "../compiled_plugins_folder/test_plugin_lib.wasm"
thread 'main' panicked at src/main.rs:80:18:
plugin@"../compiled_plugins_folder/test_plugin_lib.wasm" to have info instance
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

And I don't understand why. With "freestanding" functions inside the wit-world it works fine, but never with interfaces.

I'd appreciate any help I can get!

view this post on Zulip Nerdachse (Jul 12 2024 at 11:17):

ah, I changed the package name to package test:guest; and the call to .instance("test:guest/info") and that's how it works. I find it a bit strange that you can call a world function without having to specify the package but not an instance. Now I need to think how I can ensure that this works for all plugins, because the package (name) suddenly becomes a burden :/

view this post on Zulip Alex Crichton (Jul 12 2024 at 14:47):

You might be interseted in exploring these examples of using bindgen! to avoid writing down all the names here


Last updated: Dec 23 2024 at 14:03 UTC