英文:
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 './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')
}
And the wasm files written in Go.The original function is like this
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)
}))
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.StartQuorum
或globalThis.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("StartQuorum", ....)
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('password', bootstraps.join(','))
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论