* Remove the need for `HostRef<Store>` This commit goes through the public API of the `wasmtime` crate and removes the need for `HostRef<Store>`, as discussed in #708. This commit is accompanied with a few changes: * The `Store` type now also implements `Default`, creating a new `Engine` with default settings and returning that. * The `Store` type now implements `Clone`, and is documented as being a "cheap clone" aka being reference counted. As before there is no supported way to create a deep clone of a `Store`. * All APIs take/return `&Store` or `Store` instead of `HostRef<Store>`, and `HostRef<T>` is left as purely a detail of the C API. * The `global_exports` function is tagged as `#[doc(hidden)]` for now while we await its removal. * The `Store` type is not yet `Send` nor `Sync` due to the usage of `global_exports`, but it is intended to become so eventually. * Touch up comments on some examples * Run rustfmt
2.9 KiB
Embedding Wasmtime in Rust
This document shows how to embed Wasmtime using the Rust API, and run a simple wasm program.
Create some wasm
Let's create a simple WebAssembly file with a single exported function that returns an integer:
(;; wat2wasm hello.wat -o $WASM_FILES/hello.wasm ;;)
(module
(func (export "answer") (result i32)
i32.const 42
)
)
Create rust project
$ cargo new --bin wasmtime_hello
$ cd wasmtime_hello
$ cp $WASM_FILES/hello.wasm .
We will be using the wasmtime engine/API to run the wasm file, so we will add the dependency to Cargo.toml:
[dependencies]
wasmtime = "<current version>"
where "" is the current version number of the wasmtime crate.
It is time to add code to the src/main.rs. First, storage needs to be activated:
use wasmtime::*;
let store = Store::default();
The HostRef will be used a lot -- it is a "convenience" object to store and refer an object between the host and
the embedded environments.
The hello.wasm can be read from the file system and provided to the Module object constructor as &[u8]:
use std::fs::read;
let hello_wasm = read("hello.wasm").expect("wasm file");
let module = HostRef::new(Module::new(&store, &hello_wasm).expect("wasm module"));
The module instance can now be created. Normally, you would provide exports, but in this case, there are none required:
let instance = Instance::new(&store, &module, &[]).expect("wasm instance");
Everything is set. If a WebAssembly module has a start function -- it was run. The instance's exports can be used at this point. wasmtime provides functions to look up an export by name, and ensure that it's a function:
let answer = instance.find_export_by_name("answer").expect("answer").func().expect("function");
The exported function can be called using the call method. Remember that in most of the cases,
a HostRef<_> object will be returned, so borrow() or borrow_mut() method has to be used to refer the
specific object. The exported "answer" function accepts no parameters and returns a single i32 value.
let result = answer.borrow().call(&[]).expect("success");
println!("Answer: {}", result[0].i32());
The names of the WebAssembly module's imports and exports can be discovered by means of module's corresponding methods.
src/main.rs
use std::fs::read;
use wasmtime::*;
fn main() {
let store = Store::default();
let wasm = read("hello.wasm").expect("wasm file");
let module = HostRef::new(Module::new(&store, &wasm).expect("wasm module"));
let instance = Instance::new(&store, &module, &[]).expect("wasm instance");
let answer = instance.find_export_by_name("answer").expect("answer").func().expect("function");
let result = answer.borrow().call(&[]).expect("success");
println!("Answer: {}", result[0].i32());
}