在Vue中无法使用wasm函数。

huangapple go评论79阅读模式
英文:

Failed to use wasm function on vue

问题

当我想在Vue中使用wasm时,首先遇到的一个无法解决的问题是,我的wasm文件中的startQuorum函数找不到。

import { Go } from './wasm_exec'
import quorumWasmUrl from './lib.wasm'

export const startQuorum = async (bootstraps: Array<string>) => {
  const go = new Go()
  WebAssembly.instantiateStreaming(fetch(quorumWasmUrl), go.importObject).then(
    async (result) => {
      go.run(result.instance)
      const StartQuorum = result.instance.exports.StartQuorum as CallableFunction
      // StartQuorum is a function. but ts can not find it.
      await StartQuorum('password', bootstraps.join(','))
    }
  )
  console.log('startQuorum over')
}

以及用Go编写的wasm文件。原始函数如下:

js.Global().Set("StartQuorum", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		if qChan == nil {
			qChan = make(chan struct{}, 0)
		}
		if len(args) < 2 {
			return nil
		}
		password := args[0].String()
		bootAddrsStr := args[1].String()
		bootAddrs := strings.Split(bootAddrsStr, ",")

		handler := func() (map[string]interface{}, error) {
			ret := make(map[string]interface{})
			ok, err := StartQuorum(qChan, password, bootAddrs)
			ret["ok"] = ok
			if err != nil {
				return ret, err
			}
			return ret, nil
		}
		return Promisefy(handler)
	}))

这意味着wasm中的StartQuorum函数是存在的,但是TypeScript找不到它,浏览器返回以下错误:

Uncaught (in promise) TypeError: StartQuorum is not a function
at eval (load-quorum.ts?b7b7:139:1)

wasm文件已成功加载,我最初的诊断是TypeScript无法识别wasm中的函数。

我该如何解决这个问题?

英文:

When I want to use wasm in vue, the first thing is that I have an unsolvable problem, the startQuorum function in my wasm file can't be found.

import { Go } from &#39;./wasm_exec&#39;
import quorumWasmUrl from &#39;./lib.wasm&#39;

export const startQuorum = async (bootstraps: Array&lt;string&gt;) =&gt; {
  const go = new Go()
  WebAssembly.instantiateStreaming(fetch(quorumWasmUrl), go.importObject).then(
    async (result) =&gt; {
      go.run(result.instance)
      const StartQuorum = result.instance.exports.StartQuorum as CallableFunction
      // StartQuorum is a function. but ts can not find it.
      await StartQuorum(&#39;password&#39;, bootstraps.join(&#39;,&#39;))
    }
  )
  console.log(&#39;startQuorum over&#39;)
}

And the wasm files written in Go.The original function is like this

js.Global().Set(&quot;StartQuorum&quot;, js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		if qChan == nil {
			qChan = make(chan struct{}, 0)
		}
		if len(args) &lt; 2 {
			return nil
		}
		password := args[0].String()
		bootAddrsStr := args[1].String()
		bootAddrs := strings.Split(bootAddrsStr, &quot;,&quot;)

		handler := func() (map[string]interface{}, error) {
			ret := make(map[string]interface{})
			ok, err := StartQuorum(qChan, password, bootAddrs)
			ret[&quot;ok&quot;] = ok
			if err != nil {
				return ret, err
			}
			return ret, nil
		}
		return Promisefy(handler)
	}))

That means the StartQuorum function in wasm is existed, but typescript can't find it, browser return this.

Uncaught (in promise) TypeError: StartQuorum is not a function
at eval (load-quorum.ts?b7b7:139:1)

The wasm file is loaded well, my initial diagnosis is that ts does not recognize the functions in wasm.

How can I solve it?

答案1

得分: 1

这是因为它不是一个导出的函数。目前,Golang编译器不支持导出函数(只支持导入函数,通过魔术指令CALLIMPORT)。我之所以说“Golang编译器”,是因为如果你使用TinyGo或其他编译器,情况就不一样了。

无论如何,使用js.Global().Set将函数设置到js.Global()中,它是window/globalThis或等效的对象:

js.Global().Set("StartQuorum", ....)

这将在window/globalThis级别创建StartQuorum函数。因此,必须使用window.StartQuorum()来调用该函数。

所以,这行代码:

const StartQuorum = result.instance.exports.StartQuorum as CallableFunction
// StartQuorum is a function. but ts can not find it.

await StartQuorum('password', bootstraps.join(','))

似乎没有意义,因为result.instance.exports.StartQuorum始终为null。你的函数存在于window.StartQuorumglobalThis.StartQuorum(...)。

这不是WebAssembly的一个导出函数(它将存在于result.instance.exports中)。

英文:

That happens because it's not an exported function. Currently, Golang Compiler doesn't support export function (only importing, by magic CALLIMPORT assembly instruction). I'm saying "Golang Compiler" because that is not true if you are using TinyGo or other compiler.


Anyway, using js.Global().Set will set the function into the js.Global(), which is window/globalThis or equivalent:

js.Global().Set(&quot;StartQuorum&quot;, ....)

That is creating the StartQuorum function at the window/globalThis level. So, the function must be called using: window.StartQuorum().


So, this line:

const StartQuorum = result.instance.exports.StartQuorum as CallableFunction
// StartQuorum is a function. but ts can not find it.

await StartQuorum(&#39;password&#39;, bootstraps.join(&#39;,&#39;))

Doesn't seems to make sense, since result.instance.exports.StartQuorum is always null. Your function lives on window.StartQuorum or globalThis.StartQuorum (...).

That is not one exported function from WebAssembly (which will live at result.instance.exports.

huangapple
  • 本文由 发表于 2022年7月3日 17:38:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/72845436.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定