Skip to content

Signatures and slots

Suppose the guest imports:

wat
(import "host" "mul" (func $mul (param i32 i32) (result i32)))

Implement it in Go:

go
mul := wago.HostFunc(func(
	_ wago.HostModule,
	params []uint64,
	results []uint64,
) {
	a := wago.AsI32(params[0])
	b := wago.AsI32(params[1])
	results[0] = wago.I32(a * b)
})

Bind it during instantiation:

go
inst, err := rt.Instantiate(ctx, mod, wago.WithImports(wago.Imports{
	"host.mul": mul,
}))

The key joins the import module and field with a dot. Wago already knows the signature from the guest and rejects unsupported host values.

Scalar slots

Wasm typeRead parameterWrite result
i32wago.AsI32(params[i])results[i] = wago.I32(v)
i64wago.AsI64(params[i])results[i] = wago.I64(v)
f32wago.AsF32(params[i])results[i] = wago.F32(v)
f64wago.AsF64(params[i])results[i] = wago.F64(v)

An i32 or f32 uses the low 32 bits. A v128 occupies two adjacent little-endian slots. References use opaque tokens; never reinterpret one as a Go pointer.

The result slice is already sized for the signature. Write into it. Appending does not return another Wasm result.

Owned function references

Ordinary imports accept wago.HostFunc. A host function that may cross a public funcref boundary needs explicit runtime ownership and an exact signature:

go
owner, err := rt.NewHostFuncRef(fn, wago.FuncSig{
	Params:  []wago.ValType{wago.ValI32},
	Results: []wago.ValType{wago.ValI32},
})

Close the owner after every importing instance is done.

Next

Released under the Apache 2.0 License.