Using memory pointers
In this example we will learn how to pass data between the host system and Wasm using memory pointers.
Last updated
Was this helpful?
In this example we will learn how to pass data between the host system and Wasm using memory pointers.
Last updated
Was this helpful?
Linear memory is a major concept in WebAssembly:
The way that this memory is allocated, freed, passed, organized, etc... can vary depending on the ABI of the Wasm module.
For example, some ABIs will provide functions, either as imports or exports, for allocation and freeing of memory from the host or guest. Some Wasm ABIs may want to control their memory implicitly, for example the ABI may say that the host can reserve memory addresses 0 to 1000 for a special purpose and simply write there directly. You will want to take a look at the documentation of the ABI of your Wasm module, to see what conventions are used for memory allocation.
In this example, let's say we have a Wasm module that can perform transformations on a string passed into the module's memory. This module exports a function that returns a pointer to a fixed size static buffer. This Wasm module will take in a string, and append the string " Wasm is cool!" to the end. This example shows how we can read and write memory from the host (your Rust application), and how the Wasm module can also read and write to the same memory.
First we are going to want to initialize a new project. To do this we can navigate to our project folder, or create one. In this example, we will create a new project. Lets create it and navigate to it:
This should generate two important files for us, Cargo.toml
and src/main.rs
. The Cargo.toml
is a file that describes your project and its dependencies. The src/main.rs
is the entry point for your project, and contains the fn main() { .. }
that is run when the project is executed.
We then modify the Cargo.toml
to add the Wasmer dependencies as shown below:
Now that we have everything set up, let's go ahead and try it out!
The guest module exports a bunch of things that will be useful for us:
A memory exported as mem
;
A function to retrieve information about the memory contents exported as load
.
The load function will return two things: the offset of the contents and its length. Let's see how we can use that to read the memory.
When importing the function we tell Wasmer that it return a WasmPtr
as its first return value. This WasmPtr
is what will give us the ability to interact with the memory.
Now that we have our pointer, let's read the data. We know we are about to read a string and the load
function gave us its length. We have everything we need!
Done! We were able to get a string out of the Wasm module memory.
It's now time to write a new string int the guest module's memory. To do that will continue using our pointer.
What we do here is dereferencing the pointer to get a slice of Cell
s: we want this slice to be the size of the new string starting at the same offset as our pointer. This allows us to completely overwrite the old string with the new one.
We now have everything we need to run the WASM module, let's do it!
You should be able to run it using the cargo run
command. The output should look like this:
If you want to run the examples from the Wasmer codebase directly, you can also do: