Closed fire closed 1 year ago
Edit: I got a little carried away so here's a TL;DR: To interact with Wasm module memory from GDScript, use the stream
property of an instantiated module which adheres to the Godot's StreamPeer interface.
This is a pretty deep topic. Godot Wasm doesn't specify an API on top of strictly basic Wasm32 (in a Rust context, wasm32-unknonwn-unknown
). That means that the only types that can be natively exchanged between GDScript and the Wasm module are i32
, i64
, f32
, and f64
. If libSQL supports strings and byte arrays as well, they're doing some custom reading/writing of module memory and, in the case of strings, marshalling of the data. In short, you can either use functions with simple int/float value types or memory operations that leave you with the burden of (un)marshalling.
I decided to not reinvent the wheel for (un)marshalling data. Godot's StreamPeer interface is used to read and write from and to Wasm module memory. So to write a byte array, you can use put_data
via wasm.stream.seek(MODULE_MEMORY_POINTER).put_data(MY_PACKED_BYTE_ARRAY)
. How you determine the memory address to which to write is left up the user. That said, there's plenty of this in the visualization example. If all you need to exchange dictionaries is a byte array, this is the easiest way to do it. To exchange a string, you could use put_string
and read the UTF8 on the module side (note the first eight bytes represent string length). There's a little string exchange in the basic example that uses just the UTF8 bytes (without length header).
In the visualization example, I use an imported function that's called from the Wasm module and takes a pointer to the image buffer and a byte length as arguments. Another solution would be to use a global exported by the Wasm module to store the memory offset of the variable that will store your data on the Wasm side. For all examples, I'm using AssemblyScript, which is a super easy way to dive into Wasm if you're familiar with JS/TS. The Wasm code for the visualization example is here.
Like I said, this is a pretty deep topic. How you would exchange a dictionary is totally dependent on the data stored within that dictionary. You could use StreamPeer's put_var
method to write literally any arbitrary GDScript value to memory. However, to use this in the Wasm module, you'd have to unmarshall that value the same way Godot does.
To give me a little more context, what language are you using to create a Wasm module? I definitely recommend checking out the examples if you haven't already!
I'm ok with custom assemblyscript and c functions from wasm.
I fantasize about being able to marshal into this struct https://github.com/godotengine/godot-cpp/blob/master/gdextension/gdextension_interface.h#LL609C3-L609C23 as a wasm module.
This is the same thing but as a godot engine module. libgodot_bind
https://github.com/godotengine/godot/pull/72883/files#diff-f2aa02602c1894b5315bf1d46b13e6f195d0605c2fcb0052beb50513d098f280
Oh interesting. I see the potential in what you're saying. WebAssembly tables might make this easier to implement.
@fire Good to close? Seems like this was caused by lack of docs which is captured in https://github.com/ashtonmeuser/godot-wasm/issues/9.
We can collapse but I wouldn't close until the docs are submitted. The revised ones :D
Good point. I suppose this is as close as I've got to docs at the moment 🙃
What is the proper way to interact with godot-wasm data transfer?
libsql's wasm implementation does int(8,16,32,64), float(32,64), string and byte array. I only saw int32_t and float32_t in godot-wasm. Godot can have int64_t and float64_t.
I want some sort of array type. A dictionary can be implemented with a byte array.