我的目标是编写一个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 参数中传递来自 hello.wasm.js 文件的导入。所以我想我需要使用 hello.wasm.js 文件正确初始化wasm程序。
当我像下面那样加载wasm时,没有任何错误,并且执行了 main()函数。
<script wasm="hello.wasm" src="hello.wasm.js"></script>
但是如何从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>
问题是,如果我这样做,我的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
答案 0 :(得分:1)
最近,我本人对此进行了一些研究,据我了解,到目前为止,您的用例尚未得到真正的支持。您要找的实际上是一个库,但是如果您查看Kotlin / Native的documentation,它会指出:
支持以下二进制种类(请注意,并非所有种类都适用于所有本机平台):
[...]
sharedLib-共享的本机库-除wasm32之外的所有本机目标
staticLib-静态本机库-除wasm32外的所有本机目标
据我了解,困难在于Javascript和WebAssembly之间的数据传递,因为它仅支持int或通过线性内存的相当round回的方式。
答案 1 :(得分:0)
目前,我喜欢从事Kotlin WASM项目的工作,并且(对我的研究人员很高兴)我们的团队没有经验。抱歉,我的脑子里仍然有同样的问号,但是距离很远。
在我的案例中,我发现了wasm的许多示例,但感觉好像无法使用它们,因为在Kotlin中,情况有所不同...实际上并非如此,并且事情只是隐藏在构建过程中,我们的案子既是福也是祸。没有文档,但是科特林为我们做事!
对我来说,弥合信息空白的最佳策略是更深入地研究生成的* wasm.js文件。它看起来很恐怖,而且是JavaScript,但是实际上很容易了解Kotlin真正为您提供的功能。最好的方法:如果您查看了Api参考(https://developer.mozilla.org/en-US/docs/WebAssembly),或者只是看了一个教程,但无法应用您所看到的内容,那么最好在这里找到这些代码! >
曾经读过这篇文章并想尝试的人:您应该准备一个构建设置,该构建设置允许您将事物附加到生成的* .wasm.js文件中。在我的设置中,重要的部分:
fun addBook(book: String, numberOfBooks: Int) {
val existingNumber = books.put(book, numberOfBooks)
if (existingNumber != null)
println("Book exists, BEWARE!!")
}
对该主题有多少兴趣?
答案 2 :(得分:-1)
据我所知,您需要将函数导出到变量中以继续使用它,或者留在流式处理实例中。
所以我认为应该是这样的:
auto fn = [=,*this](){
// do things with private copies
// all updates to persist in shared state through pointers
};
#pragma omp parallel firstprivate(fn)
fn();
之后,您可以仅将变量用作函数并像这样调用它:
let helloFunc;
WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(({instance}) => {
helloFunc = instance.exports.hello;
});
否则,如果不需要导出函数供以后使用,则可以在实例内部使用它,如下所示:
helloFunc();
如果您不想像我一样使用对象解构,则可以继续将普通语法与obj.instance一起使用。