Redirects users to tested example (#791)
Rather than clutter both the README and home page with details that can drift and have caused maintenance, this directs users to the tested basic example. This also adds a FAQ entry about TinyGo's main, thanks to @basvanbeek for the help. Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -1,3 +1,36 @@
|
||||
## Basic example
|
||||
|
||||
This example shows how to use both WebAssembly and Go-defined functions with wazero.
|
||||
This example shows how to extend a Go application with an addition function
|
||||
defined in WebAssembly.
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ go run add.go 7 9
|
||||
7 + 9 = 16
|
||||
```
|
||||
|
||||
### Compilation
|
||||
|
||||
wazero is a WebAssembly runtime, embedded in your host application. To run
|
||||
WebAssembly functions, you need access to a WebAssembly Binary (Wasm),
|
||||
typically a `%.wasm` file.
|
||||
|
||||
[add.wasm](testdata/add.wasm) was compiled from [add.go](testdata/add.go) with
|
||||
[TinyGo][1], as it is the most common way to compile Go source to Wasm. Here's
|
||||
the minimal command to build a `%.wasm` binary.
|
||||
|
||||
```bash
|
||||
cd testdata; tinygo build -o add.wasm -target=wasi add.go
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
* Many other languages compile to (target) Wasm including AssemblyScript, C,
|
||||
C++, Rust, and Zig!
|
||||
* The embedding application is often called the "host" in WebAssembly.
|
||||
* The Wasm binary is often called the "guest" in WebAssembly. Sometimes they
|
||||
need [imports](../../imports) to implement features such as console output.
|
||||
TinyGo's `wasi` target, requires [WASI][2] imports.
|
||||
|
||||
[1]: https://wazero.io/languages/tinygo
|
||||
[2]: https://wazero.io/specs/#wasi
|
||||
|
||||
@@ -9,26 +9,40 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// addWasm was generated by the following:
|
||||
//
|
||||
// cd testdata; wat2wasm --debug-names add.wat
|
||||
// cd testdata; tinygo build -o add.wasm -target=wasi add.go
|
||||
//
|
||||
//go:embed testdata/add.wasm
|
||||
var addWasm []byte
|
||||
|
||||
// main implements a basic function in both Go and WebAssembly.
|
||||
// main is an example of how to extend a Go application with an addition
|
||||
// function defined in WebAssembly.
|
||||
//
|
||||
// Since addWasm was compiled with TinyGo's `wasi` target, we need to configure
|
||||
// WASI host imports.
|
||||
func main() {
|
||||
// Choose the context to use for function calls.
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a new WebAssembly Runtime.
|
||||
r := wazero.NewRuntime(ctx)
|
||||
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
|
||||
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
|
||||
WithWasmCore2())
|
||||
defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
|
||||
// Add a module to the runtime named "wasm/math" which exports one function "add", implemented in WebAssembly.
|
||||
wasm, err := r.InstantiateModuleFromBinary(ctx, addWasm)
|
||||
// Instantiate WASI, which implements host functions needed for TinyGo to
|
||||
// implement `panic`.
|
||||
if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Instantiate the guest Wasm into the same runtime. It exports the `add`
|
||||
// function, implemented in WebAssembly.
|
||||
mod, err := r.InstantiateModuleFromBinary(ctx, addWasm)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
@@ -36,14 +50,14 @@ func main() {
|
||||
// Read two args to add.
|
||||
x, y := readTwoArgs()
|
||||
|
||||
// Call the `add` function in the module and print the results to the console.
|
||||
add := wasm.ExportedFunction("add")
|
||||
// Call the `add` function and print the results to the console.
|
||||
add := mod.ExportedFunction("add")
|
||||
results, err := add.Call(ctx, x, y)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%s: %d + %d = %d\n", wasm.Name(), x, y, results[0])
|
||||
fmt.Printf("%d + %d = %d\n", x, y, results[0])
|
||||
}
|
||||
|
||||
func readTwoArgs() (uint64, uint64) {
|
||||
|
||||
@@ -12,6 +12,6 @@ import (
|
||||
// go run add.go 7 9
|
||||
func Test_main(t *testing.T) {
|
||||
stdout, _ := maintester.TestMain(t, main, "add", "7", "9")
|
||||
require.Equal(t, `wasm/math: 7 + 9 = 16
|
||||
require.Equal(t, `7 + 9 = 16
|
||||
`, stdout)
|
||||
}
|
||||
|
||||
10
examples/basic/testdata/add.go
vendored
Normal file
10
examples/basic/testdata/add.go
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
//export add
|
||||
func add(x, y uint32) uint32 {
|
||||
return x + y
|
||||
}
|
||||
|
||||
// main is required for the `wasi` target, even if it isn't used.
|
||||
// See https://wazero.io/languages/tinygo/#why-do-i-have-to-define-main
|
||||
func main() {}
|
||||
BIN
examples/basic/testdata/add.wasm
vendored
BIN
examples/basic/testdata/add.wasm
vendored
Binary file not shown.
15
examples/basic/testdata/add.wat
vendored
15
examples/basic/testdata/add.wat
vendored
@@ -1,15 +0,0 @@
|
||||
(module
|
||||
;; Define the optional module name. '$' prefixing is a part of the text format.
|
||||
$wasm/math
|
||||
|
||||
;; add returns $x+$y.
|
||||
;;
|
||||
;; Notes:
|
||||
;; * The stack begins empty and anything left must match the result type.
|
||||
;; * export allows api.Module to return this via ExportedFunction("add")
|
||||
(func (export "add") (param $x i32) (param $y i32) (result i32)
|
||||
local.get $x ;; stack: [$x]
|
||||
local.get $y ;; stack: [$x, $y]
|
||||
i32.add ;; stack: [$x+$y]
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user