Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

WASI

You can also browse this source code online and clone the wasmtime repository to run the example locally.

This example shows off how to instantiate a wasm module using WASI imports.

Wasm Source code

use std::thread::sleep;
use std::time::{Duration, Instant};

fn main() {
    println!("Hello, world!");
    let start = Instant::now();
    sleep(Duration::from_millis(100));
    println!("Napped for {:?}", Instant::now().duration_since(start));
}

wasi.cc

/*
Example of instantiating a wasm module which uses WASI imports.

You can build the example using CMake:

mkdir build && (cd build && cmake .. && \
  cmake --build . --target wasmtime-wasip1-cpp)

And then run it:

build/wasmtime-wasip1-cpp
*/

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <wasmtime.hh>

using namespace wasmtime;

static std::vector<uint8_t> read_binary_file(const char *path) {
  std::ifstream file(path, std::ios::in | std::ios::binary);
  if (!file.is_open()) {
    throw std::runtime_error(std::string("failed to open wasm file: ") + path);
  }
  std::vector<uint8_t> data((std::istreambuf_iterator<char>(file)),
                            std::istreambuf_iterator<char>());
  return data;
}

int main() {
  // Define the WASI functions globally on the `Config`.
  Engine engine;
  Linker linker(engine);
  linker.define_wasi().unwrap();

  // Create a WASI context and put it in a Store; all instances in the store
  // share this context. `WasiConfig` provides a number of ways to
  // configure what the target program will have access to.
  WasiConfig wasi;
  wasi.inherit_argv();
  wasi.inherit_stdin();
  wasi.inherit_stdout();
  wasi.inherit_stderr();

  Store store(engine);
  store.context().set_wasi(std::move(wasi)).unwrap();

  // Load and compile the wasm module.
  auto bytes = read_binary_file("target/wasm32-wasip1/debug/wasi.wasm");
  auto module =
      Module::compile(engine, Span<uint8_t>(bytes.data(), bytes.size()))
          .unwrap();

  // Define the module in the linker (anonymous name matches Rust example
  // usage).
  linker.module(store.context(), "", module).unwrap();

  // Get the default export (command entrypoint) and invoke it.
  Func default_func = linker.get_default(store.context(), "").unwrap();
  default_func.call(store, {}).unwrap();

  return 0;
}