如何从JavaScript执行Kotlin WebAssembly函数?

Mic*_*ann 7 javascript kotlin webassembly kotlin-js-interop kotlin-native

我的目标是编写一个Kotlin库,将其编译为WebAssembly并从JS调用其功能。几个小时以来,我一直在努力建立一个简单的问候世界。关于此主题的文档不存在或隐藏得很好。

这是我的kotlin文件:

@Used
public fun hello() {
    println("Hello world!")
}

fun main(args: Array<String>) {
    println("main() function executed!")
}
Run Code Online (Sandbox Code Playgroud)

当我将其编译为WebAssembly时,会得到一个hello.wasmhello.wasm.js文件。

首先,我尝试使用如下代码来执行该功能:

WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
    .then(obj => obj.instance.exports.hello());
Run Code Online (Sandbox Code Playgroud)

然后,我了解到需要在importObject参数中传递来自hello.wasm.js文件的导入。所以我想我需要使用hello.wasm.js文件正确初始化wasm程序。

当像下面那样加载wasm时,没有任何错误,并且执行了main()函数。

<script wasm="hello.wasm" src="hello.wasm.js"></script>
Run Code Online (Sandbox Code Playgroud)

但是,如何从JavaScript 执行hello()函数呢?我发现的唯一Kotlin wasm示例不是调用特定函数,而是从main()函数渲染某些内容。

此外,非常感谢与相关文档的任何链接。


更新: 我设法执行了该函数,但是我不相信这是正确的方法:

<script wasm="hello.wasm" src="hello.wasm.js"></script>
<script>
WebAssembly.instantiateStreaming(fetch('hello.wasm'), konan_dependencies)
        .then(obj => obj.instance.exports['kfun:hello$$ValueType']());
</script>
Run Code Online (Sandbox Code Playgroud)

问题是,如果我这样做,我的wasm文件将被提取两次。

仅加载没有wasm属性的hello.wasm.js文件会给我以下错误:

Uncaught Error: Could not find the wasm attribute pointing to the WebAssembly binary.
    at Object.konan.moduleEntry (stats.wasm.js:433)
    at stats.wasm.js:532
Run Code Online (Sandbox Code Playgroud)

Nic*_*ico -1

据我所知,您需要将函数导出到变量中才能继续使用它,或者留在流实例中。

所以我认为应该是这样的:

let helloFunc;

WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(({instance}) => {
helloFunc = instance.exports.hello;
});
Run Code Online (Sandbox Code Playgroud)

之后,您可以将变量用作函数并像这样调用它:

helloFunc();
Run Code Online (Sandbox Code Playgroud)

否则,如果您不需要导出该函数以供以后使用,您可以在实例内部使用它,如下所示:

WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(({instance}) => {
instance.exports.hello();
});
Run Code Online (Sandbox Code Playgroud)

如果您不想像我一样使用对象解构,您可以继续使用 obj.instance 的常规语法。