从GO编译WASM导出函数

pepwfjgg  于 2023-04-27  发布在  Go
关注(0)|答案(1)|浏览(267)

嗨,我想做一个编译一个GO文件介绍WASM和运行在从节点服务器。
index.html中,我有:

<script src="./path_to/wasm_exec.js" ></script>
    <script>
      const go = new Go();
        WebAssembly.instantiateStreaming(fetch("./path_to/file.wasm"), go.importObject).then((result) => {
          go.run(result.instance);
          console.log(result);
          console.log(go);
        });

我编译成WASM的GO文件如下所示:

package main

import (
    "fmt"
)

//export FuncName
func FuncName(M int, durations []int) int {
    fmt.Println("[GO] Log file.go", M, durations)
    return 10   
}

func main() {
    fmt.Println("HELLO GO")
}

我现在编译的是这样的:

GOOS=js GOARCH=wasm go build -o path_to/file.wasm path_to/file.go

我想在Go文件外部和html内部使用函数FuncName,但我可以导出它。

我试着这样使用tinygo:`tinygo build -o path_to/file.wasm path_to/file.go``但它不工作neather

oyxsuwqo

oyxsuwqo1#

纯粹的Go方式是使用syscall/js包将函数挂载到JavaScript全局对象(通常是windowglobal)上:

js.Global().Set("myexport", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
    //stuff
})

为了使导出的函数在页面上始终可用,Go程序不应该退出。否则,当调用导出的函数时,您将得到以下JavaScript错误:

Uncaught Error: Go program has already exited

参见wasm: re-use //export mechanism for exporting identifiers within wasm modulesGo WASM export functions
以下是更新后的演示(使用GOOS=js GOARCH=wasm go build -o main.wasm编译):

main.go

package main

import (
    "fmt"
    "syscall/js"
)

func FuncName(M int, durations []int) int {
    fmt.Println("[GO] Log file.go", M, durations)
    return 10
}

func main() {
    fmt.Println("Hello, WebAssembly!")

    // Mount the function on the JavaScript global object.
    js.Global().Set("FuncName", js.FuncOf(func(this js.Value, args []js.Value) any {
        if len(args) != 2 {
            fmt.Println("invalid number of args")
            return nil
        }
        if args[0].Type() != js.TypeNumber {
            fmt.Println("the first argument should be a number")
            return nil
        }

        arg := args[1]
        if arg.Type() != js.TypeObject {
            fmt.Println("the second argument should be an array")
            return nil
        }

        durations := make([]int, arg.Length())
        for i := 0; i < len(durations); i++ {
            item := arg.Index(i)
            if item.Type() != js.TypeNumber {
                fmt.Printf("the item at index %d should be a number\n", i)
                return nil
            }
            durations[i] = item.Int()
        }

        // Call the actual func.
        return FuncName(args[0].Int(), durations)
    }))

    // Prevent the program from exiting.
    // Note: the exported func should be released if you don't need it any more,
    // and let the program exit after then. To simplify this demo, this is
    // omitted. See https://pkg.go.dev/syscall/js#Func.Release for more information.
    select {}
}

index.html

<html>
  <head>
    <meta charset="utf-8" />
    <script src="wasm_exec.js"></script>
    <script>
      const go = new Go();
      WebAssembly.instantiateStreaming(
        fetch('main.wasm'),
        go.importObject
      ).then((result) => {
        go.run(result.instance);
      });
    </script>
  </head>
  <body>
    <button id="btn">Call FuncName</button>
    <script>
      document.getElementById('btn').addEventListener('click', () => {
        console.log(FuncName(1, [1, 2, 3, 4, 5]));
      });
    </script>
  </body>
</html>

相关问题