I’m playing around with Zig as a WASM language. I’m trying to pass a string back (or any more complicated return type). I’m trying to find the best way to do it.
Failed ideas
Multiple return values
It would be great if I could pass back an array. WASM supports multiple return values, so passing back the ptr
as an int and the len
as an int in a [2]usize
would be great, but the compiler doesn’t support it.
Something like:
export fn run(input: [*]u8, in_len: usize) [2]usize {
...
return .{@intFromPtr(output.ptr), output.len};
}
Don’t return, call JS directly
This option was to not try to return a value at all, but to call some external function to handle it. This would probably work, but I ran into another issue. I’ll post that in another thread.
EDIT: I got this option to work. It might be the option I go with.
Potential Options
Null terminated strings
One option I can think of is to go back to c-string land and allocate it as a null terminated string and pass back the pointer. Then in JS l will have to scan through the memory for the null byte and use that.
This seems like it will work, but it seems like extra work.
Pointer to Struct
Another idea that I haven’t tried yet is to allocate a packed struct and return the pointer from the struct. Then in JS I would read the two u32s from that location.
The challenge here is that I now have to allocate 2 items and remember to free them: the struct and the string.
Hardcoded Memory Location
It seems like Zig doesn’t use the first few pages of wasm memory. I could place the return value in this section in a specific spot and return the length of the string.
I don’t like this option because it seems brittle and relies on a “feature” of the compiler that could change any time.
Call for Help
Are there any other options that I missed? Any cons that I missed?