Stream: git-wasmtime

Topic: wasmtime / issue #10862 No matching implementation when l...


view this post on Zulip Wasmtime GitHub notifications bot (May 29 2025 at 16:45):

HillOfTong opened issue #10862:

After i follow guide here finishing my first cargo component project, i tried to wrote my own rust program loading wasm component with wasmtime::component module.

Here is my component code:
world.wat:

package component:hello-world;

/// An example world for the component to target.
world example {
    export hello-world: func(string) -> string;
}

lib.rs:

#[allow(warnings)]
mod bindings;

use bindings::Guest;

struct Component;

impl Guest for Component {
    /// Say hello!
    fn hello_world(test: String) -> String {
        "Hello, World!".to_string()
    }
}

bindings::export!(Component with_types_in bindings);

I compile this code to wasm with cli "cargo component build", the i copy the hello_world.wasm file to my rust project.

Here is my app code:

use anyhow::Result;
use wasmtime::*;

use std::env;

fn main() -> Result<()> {
    let engine = Engine::default();
    let mut path = env::current_dir().unwrap();
    path.push("hello_world.wasm");
    println!("file_path: {:?}", path);
    let bytes = std::fs::read(path)?;
    let my_component = wasmtime::component::Component::new(&engine, &bytes)?;

    let mut linker = wasmtime::component::Linker::new(&engine);

    let mut store = Store::new(&engine, 4);

    let instance = linker.instantiate(&mut store, &my_component)?;

    let func = instance.get_typed_func::<(String,),(String,)>(&mut store, "hello_world")?;

    let result = func.call(&mut store, ("hello_world".to_string(),))?;

    println!("result: {:?}", result);

    Ok(())
}

Error ocurred when i tried to run my app.

Error: component imports instance `wasi:cli/environment@0.2.3`, but a matching implementation was not found in the linker

Caused by:
    0: instance export `get-environment` has the wrong type
    1: function implementation is missing

So here are my questions:

  1. How to import this dependency to wasm? I tried "cargo component add wasi:cli" , but it doesn't work.
  2. I wonder if this is the right way to run component?"let result = func.call(&mut store,("hello_world".to_string(),))?; " Can i pass the string to wasm and then get the result?

THANKS!

hello_world.wasm.zip

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 03:47):

alexcrichton commented on issue #10862:

You're on the right track, and the missing piece here is that the component is importing WASI but you're not supplying that. For that you'll want to use the wasmtime-wasi crate, and you can find a number of examples throughout the documentation there. For example you might want add_to_linker_async and there's a *_sync version too to use.

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 08:04):

HillOfTong commented on issue #10862:

Thanks for you supporting!

After i follow the guide, i successfully run the wasm code.

I tried to call function which is exported from wasm, it worked well first time. When i tried to call function twice, the error occurred.

result: ("Hello from func test.",)
Error: wasm trap: cannot enter component instance

Here is my app code:

use anyhow::Result;
use wasmtime::*;

use wasmtime::component::{ResourceTable, Linker};
use wasmtime_wasi::p2::{IoView, WasiCtx, WasiView, WasiCtxBuilder};

use std::env;

struct MyState {
    table: ResourceTable,
    ctx: WasiCtx,
}

impl IoView for MyState {
    fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}
impl WasiView for MyState {
    fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx }
}


fn main() -> Result<()> {
    let engine = Engine::default();
    let mut path = env::current_dir().unwrap();
    path.push("hello_world.wasm");
    println!("file_path: {:?}", path);
    let bytes = std::fs::read(path)?;
    let my_component = wasmtime::component::Component::new(&engine, &bytes)?;
    let mut builder = WasiCtxBuilder::new();

    let mut linker = Linker::<MyState>::new(&engine);


    wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;

    let mut store = Store::new(
        &engine,
        MyState {
            ctx: builder.build(),
            table: ResourceTable::new(),
        },
    );
    let instance = linker.instantiate(&mut store, &my_component)?;

    let mut func_test = instance.get_typed_func::<(),(String,)>(&mut store, "func-test")?;

    let mut result = func_test.call(&mut store, ())?;
    println!("result: {:?}", result);


    let mut func = instance.get_typed_func::<(String,),(String,)>(&mut store, "hello-world")?;

    result = func.call(&mut store, ("WASM HELLO WORLD".to_string(),))?;
    println!("result: {:?}", result);


    Ok(())
}

So here come some questions:

  1. It seems i can only call function that exported from wasm once? How can i use wasm like a imported module?
  2. I don't understand why i need to define the struct struct MyState {table: ResourceTable, ctx: WasiCtx,} when i tried to define a component linker?

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 08:10):

bjorn3 commented on issue #10862:

After func.call() you have to call func.post_return() to run any cleanup code the guest may have. In addition while any function within a wasm component is running, you can't re-enter the same wasm component again. Only once the wasm component finishes can you re-enter it.

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 08:36):

HillOfTong commented on issue #10862:

After func.call() you have to call func.post_return() to run any cleanup code the guest may have. In addition while any function within a wasm component is running, you can't re-enter the same wasm component again. Only once the wasm component finishes can you re-enter it.

What do you mean "I can't re-enter the same wasm component again"? When i call a function within a wasm component async, i can't call any function unless it finish running?

It seems engine isn't thread-safe.Is there any function to know if it's running?

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 09:03):

bjorn3 commented on issue #10862:

When i call a function within a wasm component async, i can't call any function unless it finish running?

Yes. The wasm component likely has a single stack. If you were to call two functions at the same time, they would clobber the stack of each other, so for safety reasons the component model denies it entirely: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#component-invariants

It seems engine isn't thread-safe.Is there any function to know if it's running?

You mean the Engine type. That one is fully thread-safe and meant (though not strictly required) to be shared between all code that uses wasmtime inside a single process. As for knowing if a component currently has a function running, I'm not sure if there is an api for that.

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 09:08):

bjorn3 edited a comment on issue #10862:

When i call a function within a wasm component async, i can't call any function unless it finish running?

Yes. The wasm component likely has a single stack. If you were to call two functions at the same time, they would clobber the stack of each other, so for safety reasons the component model denies it entirely: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#component-invariants

If the function inside the wasm component is itself async in the future you should be able to use func.call_concurrent() which does allow multiple concurrent calls. While this function already exists in upstream wasmtime, it isn't yet implemented there. You have to use the wasmtime version from https://github.com/bytecodealliance/wasip3-prototyping instead, which is still experimental.

It seems engine isn't thread-safe.Is there any function to know if it's running?

You mean the Engine type. That one is fully thread-safe and meant (though not strictly required) to be shared between all code that uses wasmtime inside a single process. As for knowing if a component currently has a function running, I'm not sure if there is an api for that.

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 09:08):

bjorn3 edited a comment on issue #10862:

When i call a function within a wasm component async, i can't call any function unless it finish running?

Yes. The wasm component likely has a single stack. If you were to call two functions at the same time, they would clobber the stack of each other, so for safety reasons the component model denies it entirely: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#component-invariants

If the function inside the wasm component is itself async in the future you should be able to use func.call_concurrent() which does allow multiple concurrent calls. While this function already exists in upstream wasmtime, it isn't yet implemented there. You have to use the wasmtime version from https://github.com/bytecodealliance/wasip3-prototyping instead, which is still experimental. Native async support for the component model is still very new.

It seems engine isn't thread-safe.Is there any function to know if it's running?

You mean the Engine type. That one is fully thread-safe and meant (though not strictly required) to be shared between all code that uses wasmtime inside a single process. As for knowing if a component currently has a function running, I'm not sure if there is an api for that.

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 09:40):

HillOfTong commented on issue #10862:

Thanks!

I also want to know why i need to define strut like this. I follow the example for this link

struct MyState {
    table: ResourceTable,
    ctx: WasiCtx,
}

impl IoView for MyState {
    fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}
impl WasiView for MyState {
    fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx }
}

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 09:40):

HillOfTong edited a comment on issue #10862:

Thanks!

I also want to know why i need to define struct like this. I follow the example for this link

struct MyState {
    table: ResourceTable,
    ctx: WasiCtx,
}

impl IoView for MyState {
    fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}
impl WasiView for MyState {
    fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx }
}

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 09:40):

HillOfTong edited a comment on issue #10862:

Thanks!

I also want to know why i need to define struct like this. I follow the example for this link.

struct MyState {
    table: ResourceTable,
    ctx: WasiCtx,
}

impl IoView for MyState {
    fn table(&mut self) -> &mut ResourceTable { &mut self.table }
}
impl WasiView for MyState {
    fn ctx(&mut self) -> &mut WasiCtx { &mut self.ctx }
}

view this post on Zulip Wasmtime GitHub notifications bot (May 30 2025 at 21:08):

alexcrichton commented on issue #10862:

More-or-less, that's just how the APIs of Wasmtime are designed at this time.


Last updated: Dec 06 2025 at 07:03 UTC