wasmtime package - github.com/bytecodealliance/wasmtime-go - Go Packages (original) (raw)
Package wasmtime is a WebAssembly runtime for Go powered by Wasmtime.
This package provides everything necessary to compile and execute WebAssembly modules as part of a Go program. Wasmtime is a JIT compiler written in Rust, and can be found at https://github.com/bytecodealliance/wasmtime. This package is a binding to the C API provided by Wasmtime.
The API of this Go package is intended to mirror the Rust API (https://docs.rs/wasmtime) relatively closely, so if you find something is under-documented here then you may have luck consulting the Rust documentation as well. As always though feel free to file any issues athttps://github.com/bytecodealliance/wasmtime-go/issues/new.
It's also worth pointing out that the authors of this package up to this point primarily work in Rust, so if you've got suggestions of how to make this package more idiomatic for Go we'd love to hear your thoughts!
An example of a wasm module which calculates the GCD of two numbers
store := wasmtime.NewStore(wasmtime.NewEngine())
wasm, err := wasmtime.Wat2Wasm( (module (func $gcd (param i32 i32) (result i32) (local i32) block ;; label = @1 block ;; label = @2 local.get 0 br_if 0 (;@2;) local.get 1 local.set 2 br 1 (;@1;) end loop ;; label = @2 local.get 1 local.get 0 local.tee 2 i32.rem_u local.set 0 local.get 2 local.set 1 local.get 0 br_if 0 (;@2;) end end local.get 2 ) (export "gcd" (func $gcd)) )
)
if err != nil {
log.Fatal(err)
}
module, err := wasmtime.NewModule(store.Engine, wasm)
if err != nil {
log.Fatal(err)
}
instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
if err != nil {
log.Fatal(err)
}
run := instance.GetFunc(store, "gcd")
result, err := run.Call(store, 6, 27)
if err != nil {
log.Fatal(err)
}
fmt.Printf("gcd(6, 27) = %d\n", result.(int32))
Output:
gcd(6, 27) = 3
An example of instantiating a small wasm module which imports functionality from the host, then calling into wasm which calls back into the host.
// Almost all operations in wasmtime require a contextual store
// argument to share, so create that first
store := wasmtime.NewStore(wasmtime.NewEngine())
// Compiling modules requires WebAssembly binary input, but the wasmtime
// package also supports converting the WebAssembly text format to the
// binary format.
wasm, err := wasmtime.Wat2Wasm( (module (import "" "hello" (func $hello)) (func (export "run") (call $hello) ) )
)
if err != nil {
log.Fatal(err)
}
// Once we have our binary wasm
we can compile that into a *Module
// which represents compiled JIT code.
module, err := wasmtime.NewModule(store.Engine, wasm)
if err != nil {
log.Fatal(err)
}
// Our hello.wat
file imports one item, so we create that function
// here.
item := wasmtime.WrapFunc(store, func() {
fmt.Println("Hello from Go!")
})
// Next up we instantiate a module which is where we link in all our // imports. We've got one import so we pass that in here. instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{item}) if err != nil { log.Fatal(err) }
// After we've instantiated we can lookup our run
function and call
// it.
run := instance.GetFunc(store, "run")
_, err = run.Call(store)
if err != nil {
log.Fatal(err)
}
Output:
Hello from Go!
- func (cfg *Config) CacheConfigLoad(path string) error
- func (cfg *Config) CacheConfigLoadDefault() error
- func (cfg *Config) SetConsumeFuel(enabled bool)
- func (cfg *Config) SetCraneliftDebugVerifier(enabled bool)
- func (cfg *Config) SetCraneliftOptLevel(level OptLevel)
- func (cfg *Config) SetDebugInfo(enabled bool)
- func (cfg *Config) SetEpochInterruption(enable bool)
- func (cfg *Config) SetProfiler(profiler ProfilingStrategy)
- func (cfg *Config) SetStrategy(strat Strategy)
- func (cfg *Config) SetWasmBulkMemory(enabled bool)
- func (cfg *Config) SetWasmMemory64(enabled bool)
- func (cfg *Config) SetWasmMultiMemory(enabled bool)
- func (cfg *Config) SetWasmMultiValue(enabled bool)
- func (cfg *Config) SetWasmReferenceTypes(enabled bool)
- func (cfg *Config) SetWasmSIMD(enabled bool)
- func (cfg *Config) SetWasmThreads(enabled bool)
- func (l *Linker) AllowShadowing(allow bool)
- func (l *Linker) Define(module, name string, item AsExtern) error
- func (l *Linker) DefineFunc(store Storelike, module, name string, f interface{}) error
- func (l *Linker) DefineInstance(store Storelike, module string, instance *Instance) error
- func (l *Linker) DefineModule(store Storelike, name string, module *Module) error
- func (l *Linker) DefineWasi() error
- func (l *Linker) FuncNew(module, name string, ty *FuncType, f func(*Caller, []Val) ([]Val, *Trap)) error
- func (l *Linker) FuncWrap(module, name string, f interface{}) error
- func (l *Linker) Get(store Storelike, module, name string) *Extern
- func (l *Linker) GetDefault(store Storelike, name string) (*Func, error)
- func (l *Linker) Instantiate(store Storelike, module *Module) (*Instance, error)
- func (mem *Memory) AsExtern() C.wasmtime_extern_t
- func (mem *Memory) Data(store Storelike) unsafe.Pointer
- func (mem *Memory) DataSize(store Storelike) uintptr
- func (mem *Memory) Grow(store Storelike, delta uint64) (uint64, error)
- func (mem *Memory) Size(store Storelike) uint64
- func (mem *Memory) Type(store Storelike) *MemoryType
- func (mem *Memory) UnsafeData(store Storelike) []byte
- func (store *Store) AddFuel(fuel uint64) error
- func (store *Store) ConsumeFuel(fuel uint64) (uint64, error)
- func (store *Store) Context() *C.wasmtime_context_t
- func (store *Store) FuelConsumed() (uint64, bool)
- func (store *Store) GC()
- func (store *Store) SetEpochDeadline(deadline uint64)
- func (store *Store) SetWasi(wasi *WasiConfig)
- func (t *Table) AsExtern() C.wasmtime_extern_t
- func (t *Table) Get(store Storelike, idx uint32) (Val, error)
- func (t *Table) Grow(store Storelike, delta uint32, init Val) (uint32, error)
- func (t *Table) Set(store Storelike, idx uint32, val Val) error
- func (t *Table) Size(store Storelike) uint32
- func (t *Table) Type(store Storelike) *TableType
- func (c *WasiConfig) InheritArgv()
- func (c *WasiConfig) InheritEnv()
- func (c *WasiConfig) InheritStderr()
- func (c *WasiConfig) InheritStdin()
- func (c *WasiConfig) InheritStdout()
- func (c *WasiConfig) PreopenDir(path, guestPath string) error
- func (c *WasiConfig) SetArgv(argv []string)
- func (c *WasiConfig) SetEnv(keys, values []string)
- func (c *WasiConfig) SetStderrFile(path string) error
- func (c *WasiConfig) SetStdinFile(path string) error
- func (c *WasiConfig) SetStdoutFile(path string) error
This section is empty.
This section is empty.
func ModuleValidate(engine *Engine, wasm []byte) error
ModuleValidate validates whether `wasm` would be a valid wasm module according to the configuration in `store`
Wat2Wasm converts the text format of WebAssembly to the binary format.
Takes the text format in-memory as input, and returns either the binary encoding of the text format or an error if parsing fails.
AsExtern is an interface for all types which can be imported or exported as an Extern
type AsExternType interface { AsExternType() *ExternType }
AsExternType is an interface for all types which can be ExternType.
Caller is provided to host-defined functions when they're invoked from WebAssembly.
A `Caller` can be used for `Storelike` arguments to allow recursive execution or creation of wasm objects. Additionally `Caller` can be used to learn about the exports of the calling instance.
Implementation of the `Storelike` interface for `Caller`.
GetExport gets an exported item from the caller's module.
May return `nil` if the export doesn't, if it's not a memory, if there isn't a caller, etc.
Config holds options used to create an Engine and customize its behavior.
Example of limiting a WebAssembly function's runtime using "fuel consumption".
config := wasmtime.NewConfig() config.SetConsumeFuel(true) engine := wasmtime.NewEngineWithConfig(config) store := wasmtime.NewStore(engine) err := store.AddFuel(10000) if err != nil { log.Fatal(err) }
// Compile and instantiate a small example with an infinite loop.
wasm, err := wasmtime.Wat2Wasm( (module (func <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mi>i</mi><mi>b</mi><mi>o</mi><mi>n</mi><mi>a</mi><mi>c</mi><mi>c</mi><mi>i</mi><mo stretchy="false">(</mo><mi>p</mi><mi>a</mi><mi>r</mi><mi>a</mi><mi>m</mi></mrow><annotation encoding="application/x-tex">fibonacci (param </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">ib</span><span class="mord mathnormal">o</span><span class="mord mathnormal">na</span><span class="mord mathnormal">cc</span><span class="mord mathnormal">i</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">am</span></span></span></span>n i32) (result i32) (if (i32.lt_s (local.get $n) (i32.const 2)) (return (local.get $n)) ) (i32.add (call <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mi>i</mi><mi>b</mi><mi>o</mi><mi>n</mi><mi>a</mi><mi>c</mi><mi>c</mi><mi>i</mi><mo stretchy="false">(</mo><mi>i</mi><mn>32.</mn><mi>s</mi><mi>u</mi><mi>b</mi><mo stretchy="false">(</mo><mi>l</mi><mi>o</mi><mi>c</mi><mi>a</mi><mi>l</mi><mi mathvariant="normal">.</mi><mi>g</mi><mi>e</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">fibonacci (i32.sub (local.get </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">ib</span><span class="mord mathnormal">o</span><span class="mord mathnormal">na</span><span class="mord mathnormal">cc</span><span class="mord mathnormal">i</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mord">32.</span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">oc</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">e</span><span class="mord mathnormal">t</span></span></span></span>n) (i32.const 1))) (call <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mi>i</mi><mi>b</mi><mi>o</mi><mi>n</mi><mi>a</mi><mi>c</mi><mi>c</mi><mi>i</mi><mo stretchy="false">(</mo><mi>i</mi><mn>32.</mn><mi>s</mi><mi>u</mi><mi>b</mi><mo stretchy="false">(</mo><mi>l</mi><mi>o</mi><mi>c</mi><mi>a</mi><mi>l</mi><mi mathvariant="normal">.</mi><mi>g</mi><mi>e</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">fibonacci (i32.sub (local.get </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">ib</span><span class="mord mathnormal">o</span><span class="mord mathnormal">na</span><span class="mord mathnormal">cc</span><span class="mord mathnormal">i</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mord">32.</span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">oc</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">e</span><span class="mord mathnormal">t</span></span></span></span>n) (i32.const 2))) ) ) (export "fibonacci" (func $fibonacci)) )
)
if err != nil {
log.Fatal(err)
}
module, err := wasmtime.NewModule(store.Engine, wasm)
if err != nil {
log.Fatal(err)
}
instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
if err != nil {
log.Fatal(err)
}
// Invoke fibonacci
export with higher and higher numbers until we exhaust our fuel.
fibonacci := instance.GetFunc(store, "fibonacci")
if fibonacci == nil {
log.Fatal("Failed to find function export fibonacci
")
}
for n := 0; ; n++ {
fuelBefore, _ := store.FuelConsumed()
output, err := fibonacci.Call(store, n)
if err != nil {
break
}
fuelAfter, _ := store.FuelConsumed()
fmt.Printf("fib(%d) = %d [consumed %d fuel]\n", n, output, fuelAfter-fuelBefore)
err = store.AddFuel(fuelAfter - fuelBefore)
if err != nil {
log.Fatal(err)
}
}
Output:
fib(0) = 0 [consumed 6 fuel] fib(1) = 1 [consumed 6 fuel] fib(2) = 1 [consumed 26 fuel] fib(3) = 2 [consumed 46 fuel] fib(4) = 3 [consumed 86 fuel] fib(5) = 5 [consumed 146 fuel] fib(6) = 8 [consumed 246 fuel] fib(7) = 13 [consumed 406 fuel] fib(8) = 21 [consumed 666 fuel] fib(9) = 34 [consumed 1086 fuel] fib(10) = 55 [consumed 1766 fuel] fib(11) = 89 [consumed 2866 fuel] fib(12) = 144 [consumed 4646 fuel] fib(13) = 233 [consumed 7526 fuel]
Small example of how you can interrupt the execution of a wasm module to ensure that it doesn't run for too long.
// Enable interruptable code via Config
and then create an interrupt
// handle which we'll use later to interrupt running code.
config := wasmtime.NewConfig()
config.SetEpochInterruption(true)
engine := wasmtime.NewEngineWithConfig(config)
store := wasmtime.NewStore(engine)
store.SetEpochDeadline(1)
// Compile and instantiate a small example with an infinite loop.
wasm, err := wasmtime.Wat2Wasm( (module (func (export "run") (loop br 0) ) )
)
if err != nil {
log.Fatal(err)
}
module, err := wasmtime.NewModule(store.Engine, wasm)
if err != nil {
log.Fatal(err)
}
instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
if err != nil {
log.Fatal(err)
}
run := instance.GetFunc(store, "run")
if run == nil {
log.Fatal("Failed to find function export run
")
}
// Spin up a goroutine to send us an interrupt in a second go func() { time.Sleep(1 * time.Second) fmt.Println("Interrupting!") engine.IncrementEpoch() }()
fmt.Println("Entering infinite loop ...") _, err = run.Call(store) var trap *wasmtime.Trap if !errors.As(err, &trap) { log.Fatal("Unexpected error") }
fmt.Println("trap received...") if !strings.Contains(trap.Message(), "wasm trap: interrupt") { log.Fatalf("Unexpected trap: %s", trap.Message()) }
Output:
Entering infinite loop ... Interrupting! trap received...
An example of enabling the multi-value feature of WebAssembly and interacting with multi-value functions.
// Configure our Store
, but be sure to use a Config
that enables the
// wasm multi-value feature since it's not stable yet.
config := wasmtime.NewConfig()
config.SetWasmMultiValue(true)
store := wasmtime.NewStore(wasmtime.NewEngineWithConfig(config))
wasm, err := wasmtime.Wat2Wasm(` (module (func $f (import "" "f") (param i32 i64) (result i64 i32))
(func $g (export "g") (param i32 i64) (result i64 i32)
(call $f (local.get 0) (local.get 1))
)
(func $round_trip_many
(export "round_trip_many")
(param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64)
(result i64 i64 i64 i64 i64 i64 i64 i64 i64 i64)
local.get 0
local.get 1
local.get 2
local.get 3
local.get 4
local.get 5
local.get 6
local.get 7
local.get 8
local.get 9
)
)
`)
if err != nil { log.Fatal(err) } module, err := wasmtime.NewModule(store.Engine, wasm) if err != nil { log.Fatal(err) }
callback := wasmtime.WrapFunc(store, func(a int32, b int64) (int64, int32) { return b + 1, a + 1 })
instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{callback}) if err != nil { log.Fatal(err) }
g := instance.GetFunc(store, "g")
results, err := g.Call(store, 1, 3) if err != nil { log.Fatal(err) } arr := results.([]wasmtime.Val) a := arr[0].I64() b := arr[1].I32() fmt.Printf("> %d %d\n", a, b)
if a != 4 { log.Fatal("unexpected value for a") } if b != 2 { log.Fatal("unexpected value for b") }
roundTripMany := instance.GetFunc(store, "round_trip_many") results, err = roundTripMany.Call(store, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) if err != nil { log.Fatal(err) } arr = results.([]wasmtime.Val)
for i := 0; i < len(arr); i++ { fmt.Printf(" %d", arr[i].Get()) if arr[i].I64() != int64(i) { log.Fatal("unexpected value for arr[i]") } }
Output:
4 2 0 1 2 3 4 5 6 7 8 9
NewConfig creates a new `Config` with all default options configured.
func (cfg *Config) SetConsumeFuel(enabled bool)
SetConsumFuel configures whether fuel is enabled
func (cfg *Config) SetCraneliftDebugVerifier(enabled bool)
SetCraneliftDebugVerifier configures whether the cranelift debug verifier will be active when cranelift is used to compile wasm code.
func (cfg *Config) SetCraneliftOptLevel(level OptLevel)
SetCraneliftOptLevel configures the cranelift optimization level for generated code
func (cfg *Config) SetDebugInfo(enabled bool)
SetDebugInfo configures whether dwarf debug information for JIT code is enabled
func (cfg *Config) SetEpochInterruption(enable bool)
SetEpochInterruption enables epoch-based instrumentation of generated code to interrupt WebAssembly execution when the current engine epoch exceeds a defined threshold.
func (cfg *Config) SetProfiler(profiler ProfilingStrategy)
SetProfiler configures what profiler strategy to use for generated code
func (cfg *Config) SetStrategy(strat Strategy)
SetStrategy configures what compilation strategy is used to compile wasm code
func (cfg *Config) SetWasmBulkMemory(enabled bool)
SetWasmBulkMemory configures whether the wasm bulk memory proposal is enabled
func (cfg *Config) SetWasmMemory64(enabled bool)
SetWasmMemory64 configures whether the wasm memory64 proposal is enabled
func (cfg *Config) SetWasmMultiMemory(enabled bool)
SetWasmMultiMemory configures whether the wasm multi memory proposal is enabled
func (cfg *Config) SetWasmMultiValue(enabled bool)
SetWasmMultiValue configures whether the wasm multi value proposal is enabled
func (cfg *Config) SetWasmReferenceTypes(enabled bool)
SetWasmReferenceTypes configures whether the wasm reference types proposal is enabled
func (cfg *Config) SetWasmSIMD(enabled bool)
SetWasmSIMD configures whether the wasm SIMD proposal is enabled
func (cfg *Config) SetWasmThreads(enabled bool)
SetWasmThreads configures whether the wasm threads proposal is enabled
Engine is an instance of a wasmtime engine which is used to create a `Store`.
Engines are a form of global configuration for wasm compilations and modules and such.
NewEngine creates a new `Engine` with default configuration.
func NewEngineWithConfig(config *Config) *Engine
NewEngineWithConfig creates a new `Engine` with the `Config` provided
Note that once a `Config` is passed to this method it cannot be used again.
func (engine *Engine) IncrementEpoch()
IncrementEpoch will increase the current epoch number by 1 within the current engine which will cause any connected stores with their epoch deadline exceeded to now be interrupted.
This method is safe to call from any goroutine.
type ExportType struct {
}
ExportType is one of the exports component. A module defines a set of exports that become accessible to the host environment once the module has been instantiated.
NewExportType creates a new `ExportType` with the `name` and the type provided.
Name returns the name in the module this export type is exporting
func (ty *ExportType) Type() *ExternType
Type returns the type of item this export type expects
Extern is an external value, which is the runtime representation of an entity that can be imported or exported. It is an address denoting either a function instance, table instance, memory instance, or global instances in the shared store. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#external-values)
Func returns a Func if this export is a function or nil otherwise
func (e *Extern) Global() *Global
Global returns a Global if this export is a global or nil otherwise
func (e *Extern) Memory() *Memory
Memory returns a Memory if this export is a memory or nil otherwise
func (e *Extern) Table() *Table
Table returns a Table if this export is a table or nil otherwise
func (e *Extern) Type(store Storelike) *ExternType
Type returns the type of this export
type ExternType struct {
}
ExternType means one of external types which classify imports and external values with their respective types.
func (ty *ExternType) AsExternType() *ExternType
AsExternType returns this type itself
func (ty *ExternType) FuncType() *FuncType
FuncType returns the underlying `FuncType` for this `ExternType` if it's a function type. Otherwise returns `nil`.
func (ty *ExternType) GlobalType() *GlobalType
GlobalType returns the underlying `GlobalType` for this `ExternType` if it's a *global* type. Otherwise returns `nil`.
func (ty *ExternType) MemoryType() *MemoryType
MemoryType returns the underlying `MemoryType` for this `ExternType` if it's a *memory* type. Otherwise returns `nil`.
func (ty *ExternType) TableType() *TableType
TableType returns the underlying `TableType` for this `ExternType` if it's a *table* type. Otherwise returns `nil`.
Frame is one of activation frames which carry the return arity n of the respective function, hold the values of its locals (including arguments) in the order corresponding to their static local indices, and a reference to the function’s own module instance
FuncIndex returns the function index in the wasm module that this frame represents
FuncName returns the name, if available, for this frame's function
func (f *Frame) FuncOffset() uint
FuncOffset returns offset of this frame's instruction into the original function
ModuleName returns the name, if available, for this frame's module
func (f *Frame) ModuleOffset() uint
ModuleOffset returns offset of this frame's instruction into the original module
Func is a function instance, which is the runtime representation of a function. It effectively is a closure of the original function over the runtime module instance of its originating module. The module instance is used to resolve references to other definitions during execution of the function. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#function-instances)
func NewFunc( store Storelike, ty FuncType, f func(Caller, []Val) ([]Val, *Trap), ) *Func
NewFunc creates a new `Func` with the given `ty` which, when called, will call `f`
The `ty` given is the wasm type signature of the `Func` to create. When called the `f` callback receives two arguments. The first is a `Caller` to learn information about the calling context and the second is a list of arguments represented as a `Val`. The parameters are guaranteed to match the parameters types specified in `ty`.
The `f` callback is expected to produce one of two values. Results can be returned as an array of `[]Val`. The number and types of these results much match the `ty` given, otherwise the program will panic. The `f` callback can also produce a trap which will trigger trap unwinding in wasm, and the trap will be returned to the original caller.
If the `f` callback panics then the panic will be propagated to the caller as well.
func WrapFunc( store Storelike, f interface{}, ) *Func
WrapFunc wraps a native Go function, `f`, as a wasm `Func`.
This function differs from `NewFunc` in that it will determine the type signature of the wasm function given the input value `f`. The `f` value provided must be a Go function. It may take any number of the following types as arguments:
`int32` - a wasm `i32`
`int64` - a wasm `i64`
`float32` - a wasm `f32`
`float64` - a wasm `f64`
`*Caller` - information about the caller's instance
`*Func` - a wasm `funcref`
anything else - a wasm `externref`
The Go function may return any number of values. It can return any number of primitive wasm values (integers/floats), and the last return value may optionally be `*Trap`. If a `*Trap` returned is `nil` then the other values are returned from the wasm function. Otherwise the `*Trap` is returned and it's considered as if the host function trapped.
If the function `f` panics then the panic will be propagated to the caller.
Implementation of the `AsExtern` interface for `Func`
func (f *Func) Call(store Storelike, args ...interface{}) (interface{}, error)
Call invokes this function with the provided `args`.
This variadic function must be invoked with the correct number and type of `args` as specified by the type of this function. This property is checked at runtime. Each `args` may have one of the following types:
`int32` - a wasm `i32`
`int64` - a wasm `i64`
`float32` - a wasm `f32`
`float64` - a wasm `f64`
`Val` - correspond to a wasm value
`*Func` - a wasm `funcref`
anything else - a wasm `externref`
This function will have one of three results:
1. If the function returns successfully, then the `interface{}` return argument will be the result of the function. If there were 0 results then this value is `nil`. If there was one result then this is that result. Otherwise if there were multiple results then `[]Val` is returned.
2. If this function invocation traps, then the returned `interface{}` value will be `nil` and a non-`nil` `*Trap` will be returned with information about the trap that happened.
3. If a panic in Go ends up happening somewhere, then this function will panic.
func (f *Func) Type(store Storelike) *FuncType
Type returns the type of this func
FuncType is one of function types which classify the signature of functions, mapping a vector of parameters to a vector of results. They are also used to classify the inputs and outputs of instructions.
func NewFuncType(params, results []*ValType) *FuncType
NewFuncType creates a new `FuncType` with the `kind` provided
func (ty *FuncType) AsExternType() *ExternType
AsExternType converts this type to an instance of `ExternType`
func (ty FuncType) Params() []ValType
Params returns the parameter types of this function type
func (ty FuncType) Results() []ValType
Results returns the result types of this function type
Global is a global instance, which is the runtime representation of a global variable. It holds an individual value and a flag indicating whether it is mutable. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#global-instances)
func NewGlobal( store Storelike, ty GlobalType, val Val, ) (Global, error)
NewGlobal creates a new `Global` in the given `Store` with the specified `ty` and initial value `val`.
func (g *Global) Get(store Storelike) Val
Get gets the value of this global
func (g *Global) Set(store Storelike, val Val) error
Set sets the value of this global
func (g *Global) Type(store Storelike) *GlobalType
Type returns the type of this global
type GlobalType struct {
}
GlobalType is a ValType, which classify global variables and hold a value and can either be mutable or immutable.
func NewGlobalType(content *ValType, mutable bool) *GlobalType
NewGlobalType creates a new `GlobalType` with the `kind` provided and whether it's `mutable` or not
func (ty *GlobalType) AsExternType() *ExternType
AsExternType converts this type to an instance of `ExternType`
func (*GlobalType) Content ¶
func (ty *GlobalType) Content() *ValType
Content returns the type of value stored in this global
func (ty *GlobalType) Mutable() bool
Mutable returns whether this global type is mutable or not
type ImportType struct {
}
ImportType is one of the imports component A module defines a set of imports that are required for instantiation.
func NewImportType(module, name string, ty AsExternType) *ImportType
NewImportType creates a new `ImportType` with the given `module` and `name` and the type provided.
Module returns the name in the module this import type is importing
Name returns the name in the module this import type is importing.
Note that the returned string may be `nil` with the module linking proposal where this field is optional in the import type.
func (ty *ImportType) Type() *ExternType
Type returns the type of item this import type expects
Instance is an instantiated module instance. Once a module has been instantiated as an Instance, any exported function can be invoked externally via its function address funcaddr in the store S and an appropriate list val∗ of argument values.
func NewInstance(store Storelike, module Module, imports []AsExtern) (Instance, error)
NewInstance instantiates a WebAssembly `module` with the `imports` provided.
This function will attempt to create a new wasm instance given the provided imports. This can fail if the wrong number of imports are specified, the imports aren't of the right type, or for other resource-related issues.
This will also run the `start` function of the instance, returning an error if it traps.
func (instance Instance) Exports(store Storelike) []Extern
Exports returns a list of exports from this instance.
Each export is returned as a `*Extern` and lines up with the exports list of the associated `Module`.
func (i *Instance) GetExport(store Storelike, name string) *Extern
GetExport attempts to find an export on this instance by `name`
May return `nil` if this instance has no export named `name`
func (i *Instance) GetFunc(store Storelike, name string) *Func
GetFunc attempts to find a function on this instance by `name`.
May return `nil` if this instance has no function named `name`, it is not a function, etc.
type Linker struct { Engine *Engine
}
Linker implements a wasmtime Linking module, which can link instantiated modules together. More details you can see [examples for C](https://bytecodealliance.github.io/wasmtime/examples-c-linking.html) or [examples for Rust](https://bytecodealliance.github.io/wasmtime/examples-rust-linking.html)
store := wasmtime.NewStore(wasmtime.NewEngine())
// Compile two wasm modules where the first references the second
wasm1, err := wasmtime.Wat2Wasm( (module (import "wasm2" "double" (func $double (param i32) (result i32))) (func (export "double_and_add") (param i32 i32) (result i32) local.get 0 call $double local.get 1 i32.add ) )
)
if err != nil {
log.Fatal(err)
}
wasm2, err := wasmtime.Wat2Wasm( (module (func (export "double") (param i32) (result i32) local.get 0 i32.const 2 i32.mul ) )
)
if err != nil {
log.Fatal(err)
}
// Next compile both modules module1, err := wasmtime.NewModule(store.Engine, wasm1) if err != nil { log.Fatal(err) } module2, err := wasmtime.NewModule(store.Engine, wasm2) if err != nil { log.Fatal(err) }
linker := wasmtime.NewLinker(store.Engine)
// The second module is instantiated first since it has no imports, and // then we insert the instance back into the linker under the name // the first module expects. instance2, err := linker.Instantiate(store, module2) if err != nil { log.Fatal(err) } err = linker.DefineInstance(store, "wasm2", instance2) if err != nil { log.Fatal(err) }
// And now we can instantiate our first module, executing the result // afterwards instance1, err := linker.Instantiate(store, module1) if err != nil { log.Fatal(err) } doubleAndAdd := instance1.GetFunc(store, "double_and_add") result, err := doubleAndAdd.Call(store, 2, 3) if err != nil { log.Fatal(err) } fmt.Print(result.(int32))
Output:
7
func NewLinker(engine *Engine) *Linker
func (*Linker) AllowShadowing ¶
func (l *Linker) AllowShadowing(allow bool)
AllowShadowing configures whether names can be redefined after they've already been defined in this linker.
Define defines a new item in this linker with the given module/name pair. Returns an error if shadowing is disallowed and the module/name is already defined.
func (l *Linker) DefineFunc(store Storelike, module, name string, f interface{}) error
DefineFunc acts as a convenience wrapper to calling Define and WrapFunc.
Returns an error if shadowing is disabled and the name is already defined.
DefineInstance defines all exports of an instance provided under the module name provided.
Returns an error if shadowing is disabled and names are already defined.
DefineModule defines automatic instantiations of the module in this linker.
The `name` of the module is the name within the linker, and the `module` is the one that's being instantiated. This function automatically handles WASI Commands and Reactors for instantiation and initialization. For more information see the Rust documentation --https://docs.wasmtime.dev/api/wasmtime/struct.Linker.html#method.module.
func (l *Linker) DefineWasi() error
DefineWasi links a WASI module into this linker, ensuring that all exported functions are available for linking.
Returns an error if shadowing is disabled and names are already defined.
func (l *Linker) FuncNew(module, name string, ty FuncType, f func(Caller, []Val) ([]Val, *Trap)) error
FuncNew defines a function in this linker in the same style as `NewFunc`
Note that this function does not require a `Storelike`, which is intentional. This function can be used to insert store-independent functions into this linker which allows this linker to be used for instantiating modules in multiple different stores.
Returns an error if shadowing is disabled and the name is already defined.
func (l *Linker) FuncWrap(module, name string, f interface{}) error
FuncWrap defines a function in this linker in the same style as `WrapFunc`
Note that this function does not require a `Storelike`, which is intentional. This function can be used to insert store-independent functions into this linker which allows this linker to be used for instantiating modules in multiple different stores.
Returns an error if shadowing is disabled and the name is already defined.
func (l *Linker) Get(store Storelike, module, name string) *Extern
GetOneByName loads an item by name from this linker.
If the item isn't defined then nil is returned, otherwise the item is returned.
func (l *Linker) Instantiate(store Storelike, module Module) (Instance, error)
Instantiate instantiates a module with all imports defined in this linker.
Returns an error if the instance's imports couldn't be satisfied, had the wrong types, or if a trap happened executing the start function.
Memory instance is the runtime representation of a linear memory. It holds a vector of bytes and an optional maximum size, if one was specified at the definition site of the memory. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances) In wasmtime-go, you can get the vector of bytes by the unsafe pointer of memory from `Memory.Data()`, or go style byte slice from `Memory.UnsafeData()`
An example of working with the Memory type to read/write wasm memory.
// Create our Store
context and then compile a module and create an
// instance from the compiled module all in one go.
store := wasmtime.NewStore(wasmtime.NewEngine())
wasm, err := wasmtime.Wat2Wasm(`
(module
(memory (export "memory") 2 3)
(func (export "size") (result i32) (memory.size))
(func (export "load") (param i32) (result i32)
(i32.load8_s (local.get 0))
)
(func (export "store") (param i32 i32)
(i32.store8 (local.get 0) (local.get 1))
)
(data (i32.const 0x1000) "\01\02\03\04")
)
`)
if err != nil { log.Fatal(err) } module, err := wasmtime.NewModule(store.Engine, wasm) if err != nil { log.Fatal(err) } instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{}) if err != nil { log.Fatal(err) }
// Load up our exports from the instance memory := instance.GetExport(store, "memory").Memory() sizeFn := instance.GetFunc(store, "size") loadFn := instance.GetFunc(store, "load") storeFn := instance.GetFunc(store, "store")
// some helper functions we'll use below call32 := func(f *wasmtime.Func, args ...interface{}) int32 { ret, err := f.Call(store, args...) if err != nil { log.Fatal(err) } return ret.(int32) } call := func(f *wasmtime.Func, args ...interface{}) { _, err := f.Call(store, args...) if err != nil { log.Fatal(err) } } assertTraps := func(f *wasmtime.Func, args ...interface{}) { _, err := f.Call(store, args...) _, ok := err.(*wasmtime.Trap) if !ok { log.Fatal("expected a trap") } } assert := func(b bool) { if !b { log.Fatal("assertion failed") } }
// Check the initial memory sizes/contents assert(memory.Size(store) == 2) assert(memory.DataSize(store) == 0x20000) buf := memory.UnsafeData(store)
assert(buf[0] == 0) assert(buf[0x1000] == 1) assert(buf[0x1003] == 4)
assert(call32(sizeFn) == 2) assert(call32(loadFn, 0) == 0) assert(call32(loadFn, 0x1000) == 1) assert(call32(loadFn, 0x1003) == 4) assert(call32(loadFn, 0x1ffff) == 0) assertTraps(loadFn, 0x20000)
// We can mutate memory as well buf[0x1003] = 5 call(storeFn, 0x1002, 6) assertTraps(storeFn, 0x20000, 0)
assert(buf[0x1002] == 6) assert(buf[0x1003] == 5) assert(call32(loadFn, 0x1002) == 6) assert(call32(loadFn, 0x1003) == 5)
// And like wasm instructions, we can grow memory _, err = memory.Grow(store, 1) assert(err == nil) assert(memory.Size(store) == 3) assert(memory.DataSize(store) == 0x30000)
assert(call32(loadFn, 0x20000) == 0) call(storeFn, 0x20000, 0) assertTraps(loadFn, 0x30000) assertTraps(storeFn, 0x30000, 0)
// Memory can fail to grow _, err = memory.Grow(store, 1) assert(err != nil) _, err = memory.Grow(store, 0) assert(err == nil)
// Ensure that memory
lives long enough to cover all our usages of
// using its internal buffer we read from UnsafeData()
runtime.KeepAlive(memory)
// Finally we can also create standalone memories to get imported by // wasm modules too. memorytype := wasmtime.NewMemoryType(5, true, 5) memory2, err := wasmtime.NewMemory(store, memorytype) assert(err == nil) assert(memory2.Size(store) == 5) _, err = memory2.Grow(store, 1) assert(err != nil) _, err = memory2.Grow(store, 0) assert(err == nil)
func NewMemory(store Storelike, ty MemoryType) (Memory, error)
NewMemory creates a new `Memory` in the given `Store` with the specified `ty`.
Data returns the raw pointer in memory of where this memory starts
DataSize returns the size, in bytes, that `Data()` is valid for
Grow grows this memory by `delta` pages
Size returns the size, in wasm pages, of this memory
func (mem *Memory) Type(store Storelike) *MemoryType
Type returns the type of this memory
func (mem *Memory) UnsafeData(store Storelike) []byte
UnsafeData returns the raw memory backed by this `Memory` as a byte slice (`[]byte`).
This is not a safe method to call, hence the "unsafe" in the name. The byte slice returned from this function is not managed by the Go garbage collector. You need to ensure that `m`, the original `Memory`, lives longer than the `[]byte` returned.
Note that you may need to use `runtime.KeepAlive` to keep the original memory `m` alive for long enough while you're using the `[]byte` slice. If the `[]byte` slice is used after `m` is GC'd then that is undefined behavior.
type MemoryType struct {
}
MemoryType is one of Memory types which classify linear memories and their size range. The limits constrain the minimum and optionally the maximum size of a memory. The limits are given in units of page size.
NewMemoryType creates a new `MemoryType` with the limits on size provided
The `min` value is the minimum size, in WebAssembly pages, of this memory. The `has_max` boolean indicates whether a maximum size is present, and if so `max` is used as the maximum size of memory, in wasm pages.
Note that this will create a 32-bit memory type, the default outside of the memory64 proposal.
NewMemoryType64 creates a new 64-bit `MemoryType` with the provided limits
The `min` value is the minimum size, in WebAssembly pages, of this memory. The `has_max` boolean indicates whether a maximum size is present, and if so `max` is used as the maximum size of memory, in wasm pages.
Note that 64-bit memories are part of the memory64 WebAssembly proposal.
func (ty *MemoryType) AsExternType() *ExternType
AsExternType converts this type to an instance of `ExternType`
Is64 returns whether this is a 64-bit memory or not.
Maximum returns the maximum size of this memory, in WebAssembly pages, if specified.
If the maximum size is not specified then `(false, 0)` is returned, otherwise `(true, N)` is returned where `N` is the listed maximum size of this memory.
Minimum returns the minimum size of this memory, in WebAssembly pages
Module is a module which collects definitions for types, functions, tables, memories, and globals. In addition, it can declare imports and exports and provide initialization logic in the form of data and element segments or a start function. Modules organized WebAssembly programs as the unit of deployment, loading, and compilation.
Small example of how to serialize a compiled wasm module, and then instantiate it from the compilation artifacts.
// Configure the initial compilation environment. engine := wasmtime.NewEngine()
// Compile the wasm module into an in-memory instance of a Module
.
wasm, err := wasmtime.Wat2Wasm( (module (func $hello (import "" "hello")) (func (export "run") (call $hello)) )
)
if err != nil {
log.Fatal(err)
}
module, err := wasmtime.NewModule(engine, wasm)
if err != nil {
log.Fatal(err)
}
bytes, err := module.Serialize()
if err != nil {
log.Fatal(err)
}
// Configure the initial compilation environment. store := wasmtime.NewStore(wasmtime.NewEngine())
// Deserialize the compiled module. module, err = wasmtime.NewModuleDeserialize(store.Engine, bytes) if err != nil { log.Fatal(err) }
// Here we handle the imports of the module, which in this case is our
// helloFunc
callback.
helloFunc := wasmtime.WrapFunc(store, func() {
fmt.Println("Calling back...")
fmt.Println("> Hello World!")
})
// Once we've got that all set up we can then move to the instantiation
// phase, pairing together a compiled module as well as a set of imports.
// Note that this is where the wasm start
function, if any, would run.
instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{helloFunc})
if err != nil {
log.Fatal(err)
}
// Next we poke around a bit to extract the run
function from the module.
run := instance.GetFunc(store, "run")
if run == nil {
log.Fatal("Failed to find function export run
")
}
// And last but not least we can call it! fmt.Println("Calling export...") _, err = run.Call(store) if err != nil { log.Fatal(err) }
Output:
Calling export... Calling back...
Hello World!
NewModule compiles a new `Module` from the `wasm` provided with the given configuration in `engine`.
func NewModuleDeserialize(engine Engine, encoded []byte) (Module, error)
NewModuleDeserialize decodes and deserializes in-memory bytes previously produced by `module.Serialize()`.
This function does not take a WebAssembly binary as input. It takes as input the results of a previous call to `Serialize()`, and only takes that as input.
If deserialization is successful then a compiled module is returned, otherwise nil and an error are returned.
Note that to deserialize successfully the bytes provided must have been produced with an `Engine` that has the same compilation options as the provided engine, and from the same version of this library.
func NewModuleDeserializeFile(engine Engine, path string) (Module, error)
NewModuleDeserializeFile is the same as `NewModuleDeserialize` except that the bytes are read from a file instead of provided as an argument.
NewModuleFromFile reads the contents of the `file` provided and interprets them as either the text format or the binary format for WebAssembly.
Afterwards delegates to the `NewModule` constructor with the contents read.
func (m Module) Exports() []ExportType
Exports returns a list of `ExportType` which are the items that will be exported by this module after instantiation.
func (m Module) Imports() []ImportType
Imports returns a list of `ImportType` which are the items imported by this module and are required for instantiation
Serialize will convert this in-memory compiled module into a list of bytes.
The purpose of this method is to extract an artifact which can be stored elsewhere from this `Module`. The returned bytes can, for example, be stored on disk or in an object store. The `NewModuleDeserialize` function can be used to deserialize the returned bytes at a later date to get the module back.
OptLevel decides what degree of optimization wasmtime will perform on generated machine code
ProfilingStrategy decides what sort of profiling to enable, if any.
type Store struct {
Engine *[Engine](#Engine)
}
Store is a general group of wasm instances, and many objects must all be created with and reference the same `Store`
func NewStore(engine *Engine) *Store
NewStore creates a new `Store` from the configuration provided in `engine`
AddFuel adds fuel to this context's store for wasm to consume while executing.
For this method to work fuel consumption must be enabled via `Config.SetConsumeFuel`. By default a store starts with 0 fuel for wasm to execute with (meaning it will immediately trap). This function must be called for the store to have some fuel to allow WebAssembly to execute.
Note that at this time when fuel is entirely consumed it will cause wasm to trap. More usages of fuel are planned for the future.
If fuel is not enabled within this store then an error is returned.
ConsumeFuel attempts to manually consume fuel from the store.
If fuel consumption is not enabled via `Config.SetConsumeFuel` then this function will return an error. Otherwise this will attempt to consume the specified amount of `fuel` from the store. If successful the remaining amount of fuel is returned. If `fuel` couldn't be consumed then an error is returned.
Also note that fuel, if enabled, must be originally configured via `Store.AddFuel`.
Implementation of the `Storelike` interface
FuelConsumed returns the amount of fuel consumed by this context's store execution so far.
If fuel consumption is not enabled via `Config.SetConsumeFuel` then this function will return false. Otherwise true is returned and the fuel parameter is filled in with fuel consumed so far.
Also note that fuel, if enabled, must be originally configured via `Store.AddFuel`.
GC will clean up any `externref` values that are no longer actually referenced.
This function is not required to be called for correctness, it's only an optimization if desired to clean out any extra `externref` values.
func (store *Store) SetEpochDeadline(deadline uint64)
SetEpochDeadline will configure the relative deadline, from the current engine's epoch number, after which wasm code will be interrupted.
func (store *Store) SetWasi(wasi *WasiConfig)
SetWasi will configure the WASI state to use for instances within this `Store`.
The `wasi` argument cannot be reused for another `Store`, it's consumed by this function.
Storelike represents types that can be used to contextually reference a `Store`.
This interface is implemented by `*Store` and `*Caller` and is pervasively used throughout this library. You'll want to pass one of those two objects into functions that take a `Storelike`.
Strategy is the compilation strategies for wasmtime
Table is a table instance, which is the runtime representation of a table.
It holds a vector of reference types and an optional maximum size, if one was specified in the table type at the table’s definition site. Read more in [spec](https://webassembly.github.io/spec/core/exec/runtime.html#table-instances)
func NewTable(store Storelike, ty TableType, init Val) (Table, error)
NewTable creates a new `Table` in the given `Store` with the specified `ty`.
The `ty` must be a reference type (`funref` or `externref`) and `init` is the initial value for all table slots and must have the type specified by `ty`.
Get gets an item from this table from the specified index.
Returns an error if the index is out of bounds, or returns a value (which may be internally null) if the index is in bounds corresponding to the entry at the specified index.
Grow grows this table by the number of units specified, using the specified initializer value for new slots.
Returns an error if the table failed to grow, or the previous size of the table if growth was successful.
Set sets an item in this table at the specified index.
Returns an error if the index is out of bounds.
Size returns the size of this table in units of elements.
func (t *Table) Type(store Storelike) *TableType
Type returns the underlying type of this table
type TableType struct {
}
TableType is one of table types which classify tables over elements of element types within a size range.
NewTableType creates a new `TableType` with the `element` type provided as well as limits on its size.
The `min` value is the minimum size, in elements, of this table. The `has_max` boolean indicates whether a maximum size is present, and if so `max` is used as the maximum size of the table, in elements.
func (ty *TableType) AsExternType() *ExternType
AsExternType converts this type to an instance of `ExternType`
func (ty *TableType) Element() *ValType
Element returns the type of value stored in this table
Maximum returns the maximum size, in elements, of this table.
If no maximum size is listed then `(false, 0)` is returned, otherwise `(true, N)` is returned where `N` is the maximum size.
Minimum returns the minimum size, in elements, of this table.
Trap is the trap instruction which represents the occurrence of a trap. Traps are bubbled up through nested instruction sequences, ultimately reducing the entire program to a single trap instruction, signalling abrupt termination.
NewTrap creates a new `Trap` with the `name` and the type provided.
func (t *Trap) Code() *TrapCode
Code returns the code of the `Trap` if it exists, nil otherwise.
func (t Trap) Frames() []Frame
Frames returns the wasm function frames that make up this trap
Message returns the message of the `Trap`
TrapCode is the code of an instruction trap.
const (
StackOverflow [TrapCode](#TrapCode) = [iota](/builtin#iota)
MemoryOutOfBounds
HeapMisaligned
TableOutOfBounds
IndirectCallToNull
BadSignature
IntegerOverflow
IntegerDivisionByZero
BadConversionToInteger
UnreachableCodeReached
Interrupt
)
Val is a primitive numeric value. Moreover, in the definition of programs, immutable sequences of values occur to represent more complex data, such as text strings or other vectors.
func ValExternref(val interface{}) Val
ValExternref converts a go value to a externref Val
Using `externref` is a way to pass arbitrary Go data into a WebAssembly module for it to store. Later, when you get a `Val`, you can extract the type with the `Externref()` method.
ValF32 converts a go float32 to a f32 Val
ValF64 converts a go float64 to a f64 Val
ValFuncref converts a Func to a funcref Val
Note that `f` can be `nil` to represent a null `funcref`.
ValI32 converts a go int32 to a i32 Val
ValI64 converts a go int64 to a i64 Val
func (v Val) Externref() interface{}
Externref returns the underlying value if this is an `externref`, or panics.
Note that a null `externref` is returned as `nil`.
Small example of how to use `externref`s.
config := wasmtime.NewConfig() config.SetWasmReferenceTypes(true) store := wasmtime.NewStore(wasmtime.NewEngineWithConfig(config)) wasm, err := wasmtime.Wat2Wasm(` (module (table $table (export "table") 10 externref)
(global $global (export "global") (mut externref) (ref.null extern))
(func (export "func") (param externref) (result externref)
local.get 0
)
)
`)
if err != nil {
log.Fatal(err)
}
module, err := wasmtime.NewModule(store.Engine, wasm)
if err != nil {
log.Fatal(err)
}
instance, err := wasmtime.NewInstance(store, module, []wasmtime.AsExtern{})
if err != nil {
log.Fatal(err)
}
// Create a new externref
value.
value := wasmtime.ValExternref("Hello, World!")
// The externref
's wrapped data should be the string "Hello, World!".
externRef := value.Externref()
if externRef != "Hello, World!" {
log.Fatal("unexpected value")
}
// Lookup the table
export.
table := instance.GetExport(store, "table").Table()
// Set table[3]
to our externref
.
err = table.Set(store, 3, value)
if err != nil {
log.Fatal(err)
}
// table[3]
should now be our externref
.
tableValue, err := table.Get(store, 3)
if err != nil {
log.Fatal(err)
}
if tableValue.Externref() != externRef {
log.Fatal("unexpected value in table")
}
// Lookup the global
export.
global := instance.GetExport(store, "global").Global()
// Set the global to our externref
.
err = global.Set(store, value)
if err != nil {
log.Fatal(err)
}
// Get the global, and it should return our externref
again.
globalValue := global.Get(store)
if globalValue.Externref() != externRef {
log.Fatal("unexpected value in global")
}
// Lookup the func
export.
fn := instance.GetFunc(store, "func")
// And call it!
result, err := fn.Call(store, value)
if err != nil {
log.Fatal(err)
}
// func
returns the same reference we gave it, so results
should be
// our externref
.
if result != externRef {
log.Fatal("unexpected value from func")
}
F32 returns the underlying 32-bit float if this is an `f32`, or panics.
F64 returns the underlying 64-bit float if this is an `f64`, or panics.
Funcref returns the underlying function if this is a `funcref`, or panics.
Note that a null `funcref` is returned as `nil`.
func (v Val) Get() interface{}
Get returns the underlying 64-bit float if this is an `f64`, or panics.
I32 returns the underlying 32-bit integer if this is an `i32`, or panics.
I64 returns the underlying 64-bit integer if this is an `i64`, or panics.
Kind returns the kind of value that this `Val` contains.
ValKind enumeration of different kinds of value types
String renders this kind as a string, similar to the `*.wat` format
ValType means one of the value types, which classify the individual values that WebAssembly code can compute with and the values that a variable accepts.
func NewValType(kind ValKind) *ValType
NewValType creates a new `ValType` with the `kind` provided
func (t *ValType) Kind() ValKind
Kind returns the corresponding `ValKind` for this `ValType`
Converts this `ValType` into a string according to the string representation of `ValKind`.
type WasiConfig struct {
}
An example of linking WASI to the runtime in order to interact with the system. It uses the WAT code from https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-tutorial.md#web-assembly-text-example
dir, err := os.MkdirTemp("", "out") if err != nil { log.Fatal(err) } defer os.RemoveAll(dir) stdoutPath := filepath.Join(dir, "stdout")
engine := wasmtime.NewEngine()
// Create our module wasm, err := wasmtime.Wat2Wasm(` (module ;; Import the required fd_write WASI function which will write the given io vectors to stdout ;; The function signature for fd_write is: ;; (File Descriptor, *iovs, iovs_len, nwritten) -> Returns number of bytes written (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(memory 1)
(export "memory" (memory 0))
;; Write 'hello world\n' to memory at an offset of 8 bytes
;; Note the trailing newline which is required for the text to appear
(data (i32.const 8) "hello world\n")
(func $main (export "_start")
;; Creating a new io vector within linear memory
(i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - This is a pointer to the start of the 'hello world\n' string
(i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - The length of the 'hello world\n' string
(call $fd_write
(i32.const 1) ;; file_descriptor - 1 for stdout
(i32.const 0) ;; *iovs - The pointer to the iov array, which is stored at memory location 0
(i32.const 1) ;; iovs_len - We're printing 1 string stored in an iov - so one.
(i32.const 20) ;; nwritten - A place in memory to store the number of bytes written
)
drop ;; Discard the number of bytes written from the top of the stack
)
)
`)
if err != nil { log.Fatal(err) } module, err := wasmtime.NewModule(engine, wasm) if err != nil { log.Fatal(err) }
// Create a linker with WASI functions defined within it linker := wasmtime.NewLinker(engine) err = linker.DefineWasi() if err != nil { log.Fatal(err) }
// Configure WASI imports to write stdout into a file, and then create
// a Store
using this wasi configuration.
wasiConfig := wasmtime.NewWasiConfig()
wasiConfig.SetStdoutFile(stdoutPath)
store := wasmtime.NewStore(engine)
store.SetWasi(wasiConfig)
instance, err := linker.Instantiate(store, module)
if err != nil {
log.Fatal(err)
}
// Run the function nom := instance.GetFunc(store, "_start") _, err = nom.Call(store) if err != nil { log.Fatal(err) }
// Print WASM stdout out, err := os.ReadFile(stdoutPath) if err != nil { log.Fatal(err) } fmt.Print(string(out))
Output:
hello world
func NewWasiConfig() *WasiConfig
func (c *WasiConfig) InheritArgv()
func (c *WasiConfig) InheritEnv()
func (c *WasiConfig) InheritStderr()
func (c *WasiConfig) InheritStdin()
func (c *WasiConfig) InheritStdout()
SetArgv will explicitly configure the argv for this WASI configuration. Note that this field can only be set, it cannot be read
func (c *WasiConfig) SetEnv(keys, values []string)
SetEnv configures environment variables to be returned for this WASI configuration. The pairs provided must be an iterable list of key/value pairs of environment variables. Note that this field can only be set, it cannot be read