Как выполнить функцию Kotlin WebAssembly из JavaScript? - PullRequest
0 голосов
/ 11 января 2019

Моя цель - написать библиотеку 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());

Тогда я понял, что мне нужно передать импорт из моего файла hello.wasm.js в параметре importObject . Поэтому я думаю, что мне нужно использовать файл hello.wasm.js , чтобы правильно инициализировать мою программу wasm.

Когда я загружаю свой wasm следующим образом, я не получаю никаких ошибок, и выполняется функция main () .

<script wasm="hello.wasm" src="hello.wasm.js"></script>

Но как мне выполнить функцию hello () из JavaScript? Единственные примеры kotlin wasm, которые я обнаружил, это не вызов определенных функций, а рендеринг чего-либо из функции main () .

Также приветствуются любые ссылки на соответствующую документацию.


UPDATE: Мне удалось выполнить функцию, но я не верю, что это правильный путь:

<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 выбирается два раза, если я так делаю.

Загрузка только файла hello.wasm.js без атрибута wasm выдает мне следующую ошибку:

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

Ответы [ 2 ]

0 голосов
/ 18 марта 2019

Я недавно провел некоторые исследования в этой области, и, насколько я понимаю, ваш сценарий использования пока не поддерживается. То, что вы ищете - это, по сути, библиотека, но если вы посмотрите на документацию Kotlin / Native, в ней говорится:

Поддерживаются следующие двоичные виды (обратите внимание, что не все виды доступны для всех собственных платформ):

[...]

sharedLib - общая нативная библиотека - все нативные цели, кроме wasm32

staticLib - статическая нативная библиотека - все нативные цели, кроме wasm32

Насколько я понимаю, сложность заключается в передаче данных между Javascript и WebAssembly, поскольку она поддерживает только целочисленные значения или довольно окольный путь через линейную память.

0 голосов
/ 11 января 2019

Насколько я знаю, вам нужно будет экспортировать функцию в переменную, чтобы продолжать ее использовать, или либо оставаться в экземпляре потоковой передачи.

Так что я думаю, что это должно быть примерно так:

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.

...