Skip to content

Instantly share code, notes, and snippets.

@yurydelendik
Last active November 7, 2019 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurydelendik/377d54bc7b150899ce6494166f174338 to your computer and use it in GitHub Desktop.
Save yurydelendik/377d54bc7b150899ce6494166f174338 to your computer and use it in GitHub Desktop.

This document shows how to embed the wasmtime and run a simple wasm code.

Create 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-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:

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 "conviniece" object to store and refer an object between the host and the embedded envirnments.

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 is 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. This wasm file has only one export, so we can index it directly:

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.

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

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());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment