Embedding Wasm in Host Applications

31.1 Rust Host with Wasmtime

use wasmtime::*;

fn main() -> Result<()> {
    let mut config = Config::new();
    config.consume_fuel(true);                     // limit CPU usage
    let engine = Engine::new(&config)?;
    let module = Module::from_file(&engine, "plugin.wasm")?;

    let mut store = Store::new(&engine, ());
    store.set_fuel(1_000_000)?;

    let mut linker = Linker::new(&engine);
    linker.func_wrap("host", "log", |caller: Caller<'_, ()>, ptr: i32, len: i32| {
        let mem = caller.get_export("memory").and_then(|e| e.into_memory()).unwrap();
        let data = &mem.data(&caller)[ptr as usize..(ptr + len) as usize];
        println!("plugin says: {}", String::from_utf8_lossy(data));
    })?;

    let instance = linker.instantiate(&mut store, &module)?;
    let run = instance.get_typed_func::<(i32, i32), i32>(&mut store, "run")?;
    let result = run.call(&mut store, (2, 3))?;
    println!("result = {result}, fuel left = {}", store.get_fuel()?);
    Ok(())
}

31.2 Go Host with wazero

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/tetratelabs/wazero"
	"github.com/tetratelabs/wazero/api"
	"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)

func main() {
	ctx := context.Background()
	r := wazero.NewRuntime(ctx)
	defer r.Close(ctx)
	wasi_snapshot_preview1.MustInstantiate(ctx, r)

	_, _ = r.NewHostModuleBuilder("host").
		NewFunctionBuilder().
		WithFunc(func(ctx context.Context, m api.Module, v uint32) { fmt.Println("host got", v) }).
		Export("notify").
		Instantiate(ctx)

	wasmBytes, _ := os.ReadFile("plugin.wasm")
	mod, err := r.Instantiate(ctx, wasmBytes)
	if err != nil {
		panic(err)
	}
	res, _ := mod.ExportedFunction("add").Call(ctx, 2, 3)
	fmt.Println("add =", res[0])
}

31.3 Python Host

from wasmtime import Store, Module, Instance
store = Store()
module = Module.from_file(store.engine, "add.wasm")
instance = Instance(store, module, [])
add = instance.exports(store)["add"]
print(add(store, 2, 3))

31.4 Embedding Concerns

Resource limits: fuel/epoch interruption (CPU), StoreLimits (memory, tables, instances), timeouts.

Isolation: one Store per tenant/request, pooling allocators for fast instantiation (microseconds).

Host API design: keep imports small, versioned, and capability-oriented. Validate all pointers/lengths coming from the guest.

Precompilation and caching of modules for startup speed.