我的目标是编写一个Kotlin库,将它编译成WebAssembly,然后从JS调用它的函数。由于几个小时,我试着得到一个简单的你好世界的工作。有关此主题的文档要么不存在,要么隐藏得很好。
这是我的kotlin档案:
@Used
public fun hello() {
println("Hello world!")
}
fun main(args: Array<String>) {
println("main() function executed!")
}当我将它编译到WebAssembly时,我会得到一个hello.wasm和hello.wasm.js文件。
首先,我尝试使用这样的方法来执行函数:
WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(obj => obj.instance.exports.hello());然后,我了解到我需要在importObject参数中传递来自我的importObject文件的导入。因此,我想我需要使用hello.wasm.js文件正确地初始化我的wasm程序。
当我像下面这样加载我的wasm时,我不会收到任何错误,并且执行main()函数。
<script wasm="hello.wasm" src="hello.wasm.js"></script>但是如何从执行函数呢?我发现的唯一kotlin示例不是调用特定的函数,而是从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>问题是,如果我这样做,我的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发布于 2019-03-18 09:32:44
我最近对此进行了一些研究,据我所知,到目前为止,您的使用程序还没有得到真正的支持。您正在寻找的基本上是一个库,但是如果您查看Kotlin/Native的文档,它会声明:
支持以下二进制类型(请注意,并非所有的二进制类型都适用于所有本机平台): ..。 sharedLib -一个共享的本机库-除wasm32之外的所有本机目标 staticLib -静态本机库-除wasm32之外的所有本机目标
根据我的理解,困难在于使用Javascript和WebAssembly之间的数据传递,因为它只支持通过线性内存的it或相当迂回的方式。
发布于 2020-07-03 23:29:45
目前,我喜欢在Kotlin WASM项目上工作,(对我的研究人员来说很好),在我们的团队中没有经验。对不起,我的脑子里还有同样的问号,但已经走得很远了。
在我的例子中,我找到了很多wasm的例子,但是我觉得我无法使用它们,因为在Kotlin,事情是不同的.实际上,事实并非如此,事情只是隐藏在构建过程中,在我们的例子中,这既是一种祝福也是一种诅咒。没有多库,但是科特林为我们做了些事情!
对我来说,填补这一信息空白的最佳策略是更深入地查看生成的*wasm.js文件。它看起来可能很吓人,而且是JavaScript,但实际上很容易了解Kotlin实际上能为您做些什么。最好的方法是:如果你看了Api参考资料(https://developer.mozilla.org/en-US/docs/WebAssembly),或者你只是看了一篇教程,却无法应用你所见过的东西,你很可能会在这里找到这些代码!
谁读过这篇文章并想尝试一下:您应该准备一个构建设置,允许您将内容附加到生成的*.wasm.js文件中。在我的设置中,这方面的重要部分是:
val jsinterface by tasks.creating(Exec::class) {
val kotlincExecutable = "${project.properties["konanHome"]}/bin/kotlinc"
inputs.property("kotlincExecutable", kotlincExecutable)
outputs.file(jsInterfaceKlibFileName)
val ktFile = file(workingDir).resolve("src/wasm32Main/kotlin/js_interface/imported_js_funcs.kt")
val jsStubFile = file(workingDir).resolve("src/wasm32Main/js/stub.js")
executable(kotlincExecutable)
args(
"-include-binary", jsStubFile,
"-produce", "library",
"-o", jsInterfaceKlibFileName,
"-target", "wasm32",
ktFile
)
}
val jsinterop by tasks.creating(Exec::class) {
dependsOn(jsinterface) //inserts customized js functions on xxx.wasm.js
//jsinterop -pkg kotlinx.interop.wasm.dom -o build/klib/kotlinx.interop.wasm.dom-jsinterop.klib -target wasm32
workingDir("./")
executable("${project.properties["konanHome"]}/bin/jsinterop")
args("-pkg", "kotlinx.interop.wasm.dom", "-o", jsinteropKlibFileName.toString(), "-target", "wasm32")
}
// generate jsinterop before native compile
tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile::class).all {
dependsOn(jsinterop)
}对这个话题有多少兴趣?
发布于 2019-01-11 06:11:59
据我所知,您需要将函数导出到一个变量中,以便继续使用它,或者留在流的实例中。
所以我觉得应该是这样的
let helloFunc;
WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(({instance}) => {
helloFunc = instance.exports.hello;
});在此之后,您只需将变量作为函数使用,然后按如下方式调用:
helloFunc();否则,如果不需要导出函数以供以后使用,只需在实例中使用它,如下所示:
WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(({instance}) => {
instance.exports.hello();
});如果您不想像我所用的那样使用对象解构,您可以继续使用obj.instance的正常语法。
https://stackoverflow.com/questions/54138204
复制相似问题