Hi folks! I’m experimenting with Kotlin -> Wasm...
# webassembly
a
Hi folks! I’m experimenting with Kotlin -> Wasm compilation to run the resulting module in an embeddable Wasm runtime like WasmEdge. Rich data exchange between a host and a guest usually happens through linear memory. For example, TinyGo compiled-guests export
malloc
and
free
functions which makes it possible for a host to allocate memory up front and then pass the pointer to it when calling a guest function. There are similar options in other stacks that support compilation to Wasm. As far as I can see, Kotlin doesn’t export anything like
malloc
and it doesn’t seem to provide any means to implement it. Looks like manual memory allocation can only happen inside a
withScopedMemoryAllocator {}
so how the host is supposed to pass any non-primitive data to a guest? Is it supposed to be something like this?:
Copy code
@OptIn(UnsafeWasmMemoryApi::class)

@WasmExport("func_with_string_arg")
fun funcWithStringArg(stringSize: Int) = withScopedMemoryAllocator { allocator ->
    val ptr = allocator.allocate(stringSize)
    storeData(ptr.address.toInt()) // this calls the host which should now store the string at the provided address
    // read the data at ptr
}
This would mean the host would have to store some sort of context that should be available for the duration of the guest call. Is it the only option? It’s also not clear how to return rich data out of a function call. If I understand correctly, all allocated memory will be garbage collected on exit so returning a pointer to it wouldn’t work. The only solution I can think of is something like this:
Copy code
fun funcWithStringArg(stringSize: Int, callId Int) = withScopedMemoryAllocator { allocator ->
    // allocate a buffer for the argument
    callHostToStoreArgumentData(argBufPtr.address.toInt(), callId) // host can understand by callId arguments of which call are requested
    // execute the function body
   // store the function result data in the linear memory
    callHostToReturnResultData(resultDataPtr.address.toInt(), callId) // host can understand by callId which call returned the result
}
This is pretty convoluted and requires multiple RPC calls so this would likely affect the performance too. Would it be possible to have anything like `malloc`/`free` functions exported or to add language capabilities that would allow implementing such functions manually?
👍 1
d
Well said! Yes, allowing the host to allocate and free, even if it’s limited to just wrapping calls to WASM functions, would be huge.