After I got some trivial Wasm examples working by ...
# webassembly
m
After I got some trivial Wasm examples working by calling them directly from Kotlin without going through the JavaScript interop layer, I am now trying something more ambitious. I try to call an external Wasm function with the following profile.
Copy code
@kotlin.wasm.WasmImport("./libs/c_library.wasm", "count_vowels")
private external fun count_vowels(msg_ptr: UInt, msg_len: UInt): UInt
It is written in C and compiled via Emscripten and has been successfully tested with Chasm, Chicory and GraalVMWasm. It takes the pointer to a byte array (which represents a string) and its length as its parameters and returns the number of vowels found in this string. I am trying to call it directly from Kotlin/wasmJs like this
Copy code
@OptIn(UnsafeWasmMemoryApi::class)
private fun Pointer.storeBytes(bytes: ByteArray) {
    if (bytes.size > 0) {
        this.storeByte(bytes[0])
        for (i in 1 until bytes.size) {
            Pointer(this.address + i.toUInt()).storeByte(bytes[i])
        }
    }
}

@OptIn(UnsafeWasmMemoryApi::class)
fun countVowels(message: String): Int {
    if (message.length > 0) {
        withScopedMemoryAllocator { allocator ->
            val msgBytes = message.encodeToByteArray()
            val pointer = allocator.allocate(msgBytes.size)
            val ptr = pointer.address
            val len = msgBytes.size.toUInt()
            pointer.storeBytes(msgBytes)
            return count_vowels(ptr, len).toInt()
        }
    } else {
        return 0
    }
}
but the result is always 0. I verified the arguments on the C side and they were received correctly but the memory pointed to by
(char*)msg_ptr
is just all zeros. It seems as if the data has never been written to the linear memory of the Wasm module. Is there something wrong or did I completely misunderstand the allocator and pointer API?
I am beginning to understand why this cannot work. There is simply no way to tell the memory allocator which modules memory it should use. It is probably hard-wired to the Kotlin module and does not know anything about other imported modules like the one associated with my function. It seems to me that the current implementation is somehow incomplete with regard to this fact.
e
there's no way to know how the allocator in a different module's linear memory works
m
@ephemient Yes, that’s true but even if you know that, it does not help much because the API does not provide a way to read/write bytes from/to the linear memory of a specific module. Chasm, Chicory and GraalVMWasm do provide such an API and so could Kotlin/wasmJs as well. The component model still seems to be very far away, especially for wasmJs. Therefore an API like the ones provided by the runtimes mentioned above would be a welcomed interim solution.
e
for wasmJs, until component model arrives, I'd use JS to glue modules together. that's where the only useful APIs are for now
m
That’s what I do at the moment but I was hoping that were a more efficient way to do the parameter passing without all the intermediate type conversions and copies.