Browse Source

Add WASI async example and update the Rust WASI docs. (#7752)

pull/7756/head
Katie Bell 10 months ago
committed by GitHub
parent
commit
20079d9789
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      docs/examples-rust-wasi.md
  2. 83
      examples/wasi-async/main.rs

33
docs/examples-rust-wasi.md

@ -12,14 +12,22 @@ WebAssembly module.
[`wasmtime-wasi`]: https://crates.io/crates/wasmtime-wasi
[`Linker`]: https://docs.rs/wasmtime/*/wasmtime/struct.Linker.html
## Wasm Source code
### WebAssembly module source code
For this WASI example, this Hello World program is compiled to a WebAssembly module using the WASI Preview 1 API.
`wasi.rs`
```rust
{{#include ../examples/wasi/wasm/wasi.rs}}
```
## `wasi.rs`
Building this program generates `target/wasm32-wasi/debug/wasi.wasm`, used below.
### Invoke the WASM module
This example shows adding and configuring the WASI imports to invoke the above WASM module.
`main.rs`
```rust,ignore
{{#include ../examples/wasi/main.rs}}
```
@ -70,3 +78,24 @@ fn main() -> Result<()> {
Ok(())
}
```
## WASI Preview 2
An experimental implementation of the WASI Preview 2 API is also available, along with an adapter layer for WASI Preview 1 WebAssembly modules. In future this `preview2` API will become the default. There are some features which are currently only accessible through the `preview2` API such as async support and overriding the clock and random implementations.
### Async example
This [async example code][code2] shows how to use the [wasmtime-wasi::preview2][`preview2`] module to
execute the same WASI Preview 1 WebAssembly module from the example above. This example requires the `wasmtime` crate `async` feature to be enabled.
This does not require any change to the WebAssembly module, it's just the WASI API host functions which are implemented to be async. See [wasmtime async support](https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.async_support).
[code2]: https://github.com/bytecodealliance/wasmtime/blob/main/examples/wasi-async/main.rs
[`preview2`]: https://docs.rs/wasmtime-wasi/latest/wasmtime_wasi/preview2/index.html
```rust,ignore
{{#include ../examples/wasi-async/main.rs}}
```
You can also [browse this source code online][code2] and clone the wasmtime
repository to run the example locally.

83
examples/wasi-async/main.rs

@ -0,0 +1,83 @@
//! Example of instantiating a wasm module which uses WASI preview1 imports
//! implemented through the async preview2 WASI implementation.
/*
You can execute this example with:
cmake examples/
cargo run --example wasi-async
*/
use anyhow::Result;
use wasmtime::{Config, Engine, Linker, Module, Store};
use wasmtime_wasi::preview2;
struct WasiHostCtx {
preview2_ctx: preview2::WasiCtx,
preview2_table: wasmtime::component::ResourceTable,
preview1_adapter: preview2::preview1::WasiPreview1Adapter,
}
impl preview2::WasiView for WasiHostCtx {
fn table(&self) -> &wasmtime::component::ResourceTable {
&self.preview2_table
}
fn table_mut(&mut self) -> &mut wasmtime::component::ResourceTable {
&mut self.preview2_table
}
fn ctx(&self) -> &preview2::WasiCtx {
&self.preview2_ctx
}
fn ctx_mut(&mut self) -> &mut preview2::WasiCtx {
&mut self.preview2_ctx
}
}
impl preview2::preview1::WasiPreview1View for WasiHostCtx {
fn adapter(&self) -> &preview2::preview1::WasiPreview1Adapter {
&self.preview1_adapter
}
fn adapter_mut(&mut self) -> &mut preview2::preview1::WasiPreview1Adapter {
&mut self.preview1_adapter
}
}
#[tokio::main]
async fn main() -> Result<()> {
// Construct the wasm engine with async support enabled.
let mut config = Config::new();
config.async_support(true);
let engine = Engine::new(&config)?;
// Add the WASI preview1 API to the linker (will be implemented in terms of
// the preview2 API)
let mut linker: Linker<WasiHostCtx> = Linker::new(&engine);
preview2::preview1::add_to_linker_async(&mut linker)?;
// Add capabilities (e.g. filesystem access) to the WASI preview2 context here.
let wasi_ctx = preview2::WasiCtxBuilder::new().inherit_stdio().build();
let host_ctx = WasiHostCtx {
preview2_ctx: wasi_ctx,
preview2_table: preview2::ResourceTable::new(),
preview1_adapter: preview2::preview1::WasiPreview1Adapter::new(),
};
let mut store: Store<WasiHostCtx> = Store::new(&engine, host_ctx);
// Instantiate our 'Hello World' wasm module.
// Note: This is a module built against the preview1 WASI API.
let module = Module::from_file(&engine, "target/wasm32-wasi/debug/wasi.wasm")?;
let func = linker
.module_async(&mut store, "", &module)
.await?
.get_default(&mut store, "")?
.typed::<(), ()>(&store)?;
// Invoke the WASI program default function.
func.call_async(&mut store, ()).await?;
Ok(())
}
Loading…
Cancel
Save