github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/examples/basic/add.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	_ "embed"
     6  	"errors"
     7  	"flag"
     8  	"fmt"
     9  	"log"
    10  	"strconv"
    11  
    12  	"github.com/bananabytelabs/wazero"
    13  	"github.com/bananabytelabs/wazero/imports/wasi_snapshot_preview1"
    14  )
    15  
    16  // addWasm was generated by the following:
    17  //
    18  //	cd testdata; tinygo build -o add.wasm -target=wasi add.go
    19  //
    20  //go:embed testdata/add.wasm
    21  var addWasm []byte
    22  
    23  // main is an example of how to extend a Go application with an addition
    24  // function defined in WebAssembly.
    25  //
    26  // Since addWasm was compiled with TinyGo's `wasi` target, we need to configure
    27  // WASI host imports.
    28  func main() {
    29  	// Parse positional arguments.
    30  	flag.Parse()
    31  
    32  	// Choose the context to use for function calls.
    33  	ctx := context.Background()
    34  
    35  	// Create a new WebAssembly Runtime.
    36  	r := wazero.NewRuntime(ctx)
    37  	defer r.Close(ctx) // This closes everything this Runtime created.
    38  
    39  	// Instantiate WASI, which implements host functions needed for TinyGo to
    40  	// implement `panic`.
    41  	wasi_snapshot_preview1.MustInstantiate(ctx, r)
    42  
    43  	// Instantiate the guest Wasm into the same runtime. It exports the `add`
    44  	// function, implemented in WebAssembly.
    45  	mod, err := r.Instantiate(ctx, addWasm)
    46  	if err != nil {
    47  		log.Panicf("failed to instantiate module: %v", err)
    48  	}
    49  
    50  	// Read two args to add.
    51  	x, y, err := readTwoArgs(flag.Arg(0), flag.Arg(1))
    52  	if err != nil {
    53  		log.Panicf("failed to read arguments: %v", err)
    54  	}
    55  
    56  	// Call the `add` function and print the results to the console.
    57  	add := mod.ExportedFunction("add")
    58  	results, err := add.Call(ctx, x, y)
    59  	if err != nil {
    60  		log.Panicf("failed to call add: %v", err)
    61  	}
    62  
    63  	fmt.Printf("%d + %d = %d\n", x, y, results[0])
    64  }
    65  
    66  func readTwoArgs(xs, ys string) (uint64, uint64, error) {
    67  	if xs == "" || ys == "" {
    68  		return 0, 0, errors.New("must specify two command line arguments")
    69  	}
    70  
    71  	x, err := strconv.ParseUint(xs, 10, 64)
    72  	if err != nil {
    73  		return 0, 0, fmt.Errorf("argument X: %v", err)
    74  	}
    75  
    76  	y, err := strconv.ParseUint(ys, 10, 64)
    77  	if err != nil {
    78  		return 0, 0, fmt.Errorf("argument Y: %v", err)
    79  	}
    80  
    81  	return x, y, nil
    82  }