How do I get accsess to the memory buffer
QuarkNerd opened this issue · 5 comments
Sorry if this is a silly question.
But I am able to access the classes/struct and the functions form inside my javascript (svelte). But I can't seem to see the memory buffer.
The memory buffer is normally exported by index_bg.wasm
By default Wasm modules do not export anything, so you have to manually export the things that you want:
#[wasm_bindgen]
pub fn memory() -> JsValue {
wasm_bindgen::memory()
}
Though you usually shouldn't need to access the memory buffer directly, what is your use case?
I can see export const memory: WebAssembly.Memory;
and readonly memory: WebAssembly.Memory;
in the ts files made in target
and previously have been able to use memory without explicitly exporting it (when I wasn't using rollup).
If I try your suggestion I get
0: failed to parse export section
1: duplicate export name (at offset 3704)
My use case is to get the data for a display (simple on/off pixels, no colour) to render with JS.
Kind of like this tutorial (except Im making an emulator)
The tutorial suggests that rendering directly from memory is better than generating strrings to pass to JS
You aren't supposed to use the values from index_bg.wasm
since it's an implementation detail, and it will disappear after esm-integration is implemented.
If I try your suggestion I get
Ah, right, there's probably some sort of name conflict, so name it something else like wasm_memory
.
The tutorial suggests that rendering directly from memory is better than generating strrings to pass to JS
That is very true, however you shouldn't be using the memory directly, since it requires you to mess around with the byte alignment and offset.
Instead, you should just have a Rust function/method which returns a Uint8Array
and then you can use Uint8Array::view
to send a Rust slice to JS:
#[wasm_bindgen]
pub fn get_slice(&self) -> Uint8Array {
unsafe { Uint8Array::view(&self.my_slice) }
}
This does not copy the bytes (it just indexes directly into Wasm's memory), so it is very fast, but you have to uphold the safety guarantees.
The safety guarantees are quite simple: after you create the Uint8Array
, you must not call any Rust functions until the JS code is done using the Uint8Array
. Also, you must not access the Uint8Array
after the slice is dropped.
If you don't want to deal with the unsafe
requirements, you can instead use Uint8Array::from
which will make a copy of the bytes. Even though it copies, this is still a lot faster than sending a string.
The Life tutorial is quite old (and outdated), it was created before Uint8Array::view
existed. Nowadays there is almost no reason to use Wasm's memory, since you can just use Uint8Array::view
instead (which does the same thing but far better).
In addition to Uint8Array
, there is also Int8Array
, Int16Array
, Int32Array
, Uint16Array
, Uint32Array
, Float32Array
, and Float64Array
.
Thank you very much for the help
Of course.