diff options
author | Andrew Clayton <a.clayton@nginx.com> | 2023-10-25 19:41:47 +0100 |
---|---|---|
committer | Andrew Clayton <a.clayton@nginx.com> | 2023-10-25 19:57:13 +0100 |
commit | 3aed80812e105cd99c43f11023012608aecd9f4a (patch) | |
tree | ef078ea7efe8f5024294cb698d6fb47be2891c25 /rust/hello_world/src | |
parent | 510d3becc7592405f02e90f5aa43740c53f7deeb (diff) | |
download | project_blackbird-3aed80812e105cd99c43f11023012608aecd9f4a.tar.gz project_blackbird-3aed80812e105cd99c43f11023012608aecd9f4a.tar.bz2 |
Add a component model example
This adds the 'Hello World' example from here[0]. The runtime is in Rust
and the component is in C.
This requires some new tools
- https://github.com/bytecodealliance/wit-bindgen
- https://github.com/bytecodealliance/wasm-tools
You can use the pre-built packages, once downloaded and untar'd, edit
rust/hello_world/component/Makefile
and adjust the paths for the above tools.
To build the component with make you may need to specify where the WASI
sysroot is
$ make WASI_SYSROOT=/path/to/wasi-sysroot
[0]: <https://docs.rs/wasmtime/latest/wasmtime/component/macro.bindgen.html>
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
Diffstat (limited to 'rust/hello_world/src')
-rw-r--r-- | rust/hello_world/src/main.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/rust/hello_world/src/main.rs b/rust/hello_world/src/main.rs new file mode 100644 index 0000000..98b16bb --- /dev/null +++ b/rust/hello_world/src/main.rs @@ -0,0 +1,62 @@ +/* + * Example from + * https://docs.rs/wasmtime/latest/wasmtime/component/macro.bindgen.html + */ + +use wasmtime::component::*; +use wasmtime::{Config, Engine, Store}; + +bindgen!(); + +struct MyState { + name: String, +} + +// Imports into the world, like the `name` import for this world, are satisfied +// through traits. +impl HelloWorldImports for MyState { + // Note the `Result` return value here where `Ok` is returned back to + // the component and `Err` will raise a trap. + fn name(&mut self) -> wasmtime::Result<String> { + Ok(self.name.clone()) + } +} + +fn main() -> wasmtime::Result<()> { + // Configure an `Engine` and compile the `Component` that is being run for + // the application. + let mut config = Config::new(); + config.wasm_component_model(true); + let engine = Engine::new(&config)?; + let component = Component::from_file(&engine, + "component/hello_world-component.wasm")?; + + // Instantiation of bindings always happens through a `Linker`. + // Configuration of the linker is done through a generated `add_to_linker` + // method on the bindings structure. + // + // Note that the closure provided here is a projection from `T` in + // `Store<T>` to `&mut U` where `U` implements the `HelloWorldImports` + // trait. In this case the `T`, `MyState`, is stored directly in the + // structure so no projection is necessary here. + let mut linker = Linker::new(&engine); + HelloWorld::add_to_linker(&mut linker, |state: &mut MyState| state)?; + + // As with the core wasm API of Wasmtime instantiation occurs within a + // `Store`. The bindings structure contains an `instantiate` method which + // takes the store, component, and linker. This returns the `bindings` + // structure which is an instance of `HelloWorld` and supports typed access + // to the exports of the component. + let mut store = Store::new( + &engine, + MyState { + name: "me".to_string(), + }, + ); + let (bindings, _) = HelloWorld::instantiate(&mut store, &component, &linker)?; + + // Here our `greet` function doesn't take any parameters for the component, + // but in the Wasmtime embedding API the first argument is always a `Store`. + bindings.call_greet(&mut store)?; + Ok(()) +} |