I have been trying to pass a string to a Rust function (compiled to Wasm), however for what I understood, right now there is no way to pass strings directy, because the "str" is not a type in the "FFI world" (at least that's what the rust compiler is saying):
= help: consider using `*const u8` and a length instead
So what I did was changing the function to this form (instead of using a simple &str type):
#[no_mangle]
pub extern "C" fn greet(s: *mut u8, len: usize) {
let s = std::str::from_utf8(unsafe { std::slice::from_raw_parts(s, len) }).unwrap();
println!("Hello, {}!", s)
}
This means that I need a pointer and the length of the string in u8.
However, someone made me notice that WASM modules are sandboxed, so they can't use normal pointers like normal applications. Thus, I have to use a function like this one to allocate memory into the module's linear memory:
use std::alloc::{alloc, dealloc, Layout};
#[no_mangle]
pub unsafe fn my_alloc(len: usize) -> *mut u8 {
let align = std::mem::align_of::<usize>();
let layout = Layout::from_size_align_unchecked(size, align);
alloc(layout)
}
This is an example of a JS function that uses an alloc function like this one:
function copyMemory(data, instance) {
var ptr = instance.exports.alloc(data.length);
var mem = new Uint8Array(instance.exports.memory.buffer, ptr, data.length);
mem.set(new Uint8Array(data));
return ptr;
}
My problem is that I don't know how to convert this function to Go, that's because I am stuck at the "var mem" line, for these reasons:
- I can't find the equivalent of "instance.exports.memory.buffer" in Go (instance is a "*wasmtime.Instance" type).
- I don't know how to do what Unit8Buffer does in Go.
Good read about memory in Wasm: (https://radu-matei.com/blog/practical-guide-to-wasm-memory/#exchanging-strings-between-modules-and-runtimes)