Files
wasmtime/docs/embed-rust.md
Dan Gohman 43b761ef5f Update the top-level README.md and embedding documentation. (#508)
* Update the top-level README.md and embedding documentation.

wasmtime-api is now the primary external API crate, so recommend that
instead of wasmtime-jit.

Also, enable wasmtime-api's C API by default, so that it shows up on
docs.rs, and to make it easier to use.

And, add basic embedding documentation and link to it from the
README.md. Credit to @yurydelendik for the content.

* Use the new wasm-c-api URL.

* Don't pass --features wasm-c-api, as it is now on by default.
2019-11-07 16:47:54 -08:00

100 lines
2.9 KiB
Markdown

# 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:
```wat
(;; 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-api = { git = "https://github.com/CraneStation/wasmtime" }
```
It is time to add code to the `src/main.rs`. First, the engine and storage need to be activated:
```rust
use wasmtime_api::*;
let engine = HostRef::new(Engine::default());
let store = HostRef::new(Store::new(&engine));
```
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]`:
```rust
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 is none required:
```rust
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. This wasm file has only one export, so we can index it directly:
```rust
let answer_fn = instance.exports()[0].func().expect("answer 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.
```rust
let result = answer_fn.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
```rust
use std::fs::read;
use wasmtime_api::*;
fn main() {
let engine = HostRef::new(Engine::default());
let store = HostRef::new(Store::new(&engine));
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_fn = instance.exports()[0].func().expect("answer function");
let result = answer_fn.borrow().call(&[]).expect("success");
println!("Answer: {}", result[0].i32());
}
```