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; }#[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 missingSo here are my questions:
- How to import this dependency to wasm? I tried "cargo component add wasi:cli" , but it doesn't work.
- 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!
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-wasicrate, and you can find a number of examples throughout the documentation there. For example you might wantadd_to_linker_asyncand there's a*_syncversion too to use.
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 instanceHere 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:
- It seems i can only call function that exported from wasm once? How can i use wasm like a imported module?
- 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?
bjorn3 commented on issue #10862:
After
func.call()you have to callfunc.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.
HillOfTong commented on issue #10862:
After
func.call()you have to callfunc.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?
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
Enginetype. 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.
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
Enginetype. 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.
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
Enginetype. 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.
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 } }
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 } }
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 } }
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