Interacting with memory
This example illustrates the basics of the basics of interacting with WASM module memory.
A WASM module can export its memory. With Wasmer you'll be able to interact with this memory.
In this example we'll illustrate the basics of interacting with the module memory:
How to query information about the memory;
How to load read from the memory;
How to write to the memory.
There are mainly two ways of interacting with the memory, either through exported function or by calling the memory API directly. It really depends on how the memory is exported.
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:
cargo new memory
cd memory
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:
[package]
name = "memory"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
edition = "2018"
[dependencies]
# The Wasmer API
wasmer = "1.0.0-alpha5"
Now that we have everything set up, let's go ahead and try it out!
Querying memory information
The first interesting thing to do is to query information about the memory. To do that we must either have access to the memory (i.e it has to be exported) or we must have access to an exported function which is able to give us this information.
let mem_size: NativeFunc<(), i32> = instance
.exports
.get_native_function("mem_size")?;
let memory = instance.exports.get_memory("memory")?;
assert_eq!(memory.size(), Pages::from(1));
assert_eq!(memory.size().bytes(), Bytes::from(65536 as usize));
assert_eq!(memory.data_size(), 65536);
let result = mem_size.call()?;
assert_eq!(Pages::from(result as u32), memory.size());
Now that we know the size of our memory it's time to see how we can change this.
Growing the memory
A memory can be grown to allow storing more things into it. This is easily done through
memory.grow(2)?;
assert_eq!(memory.size(), Pages::from(3));
assert_eq!(memory.data_size(), 65536 * 3);
To grow a memory you have to call the dedicated method and provide the number of pages, called the delta, you want to add to the memory.
Reading from and writing to the memory
Now that we know how to query and adjust the size of the memory, let's see how we can write to it or read from it.
We'll only focus on how to do this using exported functions, the goal is to show how to work with memory addresses.
Let's start by using absolute memory addresses to write and read a value.
let get_at: NativeFunc<i32, i32> = instance
.exports
.get_native_function("get_at")?;
let set_at: NativeFunc<(i32, i32), ()> = instance
.exports
.get_native_function("set_at")?;
let mem_addr = 0x2220;
let val = 0xFEFEFFE;
set_at.call(mem_addr, val)?;
let result = get_at.call(mem_addr)?;
println!("Value at {:#x?}: {:?}", mem_addr, result);
Now assume we want to write a value at the end of the second memory page and the read it. Let's see how we can do that:
let page_size = 0x1_0000;
let mem_addr = (page_size * 2) - mem::size_of_val(&val) as i32;
let val = 0xFEA09;
set_at.call(mem_addr, val)?;
let result = get_at.call(mem_addr)?;
println!("Value at {:#x?}: {:?}", mem_addr, result);
As you can see here we can use the size of a page and the size of the value we want to write to compute an address and write to it.
It enough for now: we only covered how to interact with the memory through exported functions. If you want to know more, see the following example:
Using memory pointersRunning
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:
Compiling module...
Instantiating module...
Querying memory size...
Memory size: 1
Growing memory...
Value at 0x2220: 267382782
Value at 0x1fffc: 1042953
Last updated
Was this helpful?