Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

574
Vistas
How to execute Kotlin WebAssembly function from JavaScript?

My goal is to write a Kotlin library, compile it to WebAssembly and call its functions from JS. Since a few hours I try to get a simple hello world to work. The documentation on this topic is either non existent or well hidden.

This is my kotlin file:

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

fun main(args: Array<String>) {
    println("main() function executed!")
}

When I compile it to WebAssembly, I get a hello.wasm and hello.wasm.js file.

First I tried to use something like this to execute the function:

WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
    .then(obj => obj.instance.exports.hello());

Then I understood that I need to pass the imports from my hello.wasm.js file in the importObject parameter. So I guess that I need to use the hello.wasm.js file to correctly initialize my wasm program.

When I load my wasm like the following, I don't get any errors and the main() function is executed.

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

But how can I execute the hello() function from JavaScript? The only kotlin wasm examples I found are not calling specific functions but rendering something from the main() function.

Also any links to relevant documentation are very much appreciated.


UPDATE: I managed to execute the function, but I don't believe this is the correct way:

<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>

The problem is, that my wasm file is fetched two times if I do it like that.

Loading only the hello.wasm.js file without the wasm attribute gets me the following error:

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
over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

I recently did some research into this myself and from my understanding, your usecase is not really supported so far. What you are looking for is essentially a library, yet if you look into the documentation of Kotlin/Native it states:

The following binary kinds are supported (note that not all the kinds are available for all native platforms):

[...]

sharedLib - a shared native library - all native targets except wasm32

staticLib - a static native library - all native targets except wasm32

From my understanding, the difficulty lies withing data passing between Javascript and WebAssembly as it only supports ints or the rather roundabout way via linear memory.

over 4 years ago · Santiago Trujillo Denunciar

0

Currently I enjoy working on a Kotlin WASM project and (nice for the researcher in me) there is no experience in our team. Sorry, I still have that same question mark in my head but got it quite far.

In my case, I found many examples for wasm, but it felt like I couldn't use them, because in Kotlin things were different... Actually this is not the case and things are just hidden in build processes which in our case is both a blessing and a curse. There is no docu, but kotlin does things for us!

For me the best strategy to fill that gap of information is to have a deeper look into the generated *wasm.js file. It might look scary and it is JavaScript, but it is actually quite easy to get an idea of what Kotlin is actually capable to do for you. The best: If you had a look on the Api references (https://developer.mozilla.org/en-US/docs/WebAssembly) or you just watched a tutorial but could not apply what you have seenn, chances are best that you will find these pieces of code in here!

Who ever reads this and wants to try things out: You should prepare a build setup that allows you to append things to the generated *.wasm.js file. The important parts for this in my setup:

    
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)
}

How many interest is on that topic?

over 4 years ago · Santiago Trujillo Denunciar

0

As far as I know you will need to export the function into a variable to keep using it, or either stay in the instance of the streaming.

So I think it should be something like this:

let helloFunc;

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

after that you can just use your variable as a function and call it like this:

helloFunc();

Otherwise if you don't need to export the function for later use you can just use it inside of the instance like this:

WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
.then(({instance}) => {
instance.exports.hello();
});

If you don't want to use the object deconstruction like I used, you can keep using your normal syntax with obj.instance.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda