Last active
March 10, 2023 14:59
-
-
Save Denys-Bushulyak/2531f297a85d048e17b8a067262f13b1 to your computer and use it in GitHub Desktop.
This gist show examples how to use webassembly memory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::ffi::CString; | |
use std::mem::forget; | |
use wasmtime::{Instance, Module, Store}; | |
// | |
// Code of module which have to be compiled to wasm library | |
// | |
// use std::alloc::{alloc, Layout}; | |
// use std::ffi::CString; | |
// use std::mem::forget; | |
// | |
// #[no_mangle] | |
// pub fn allocate_memory(size: usize) -> *mut u8 { | |
// let align = std::mem::align_of::<usize>(); | |
// let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; | |
// unsafe { alloc(layout) } | |
// } | |
// | |
// #[no_mangle] | |
// pub fn add_end(ptr: *const u8) -> usize { | |
// let text = unsafe { CString::from_raw(ptr as *mut _) }; | |
// let mut text = text.into_bytes(); | |
// text.extend(b" (FIN)\0"); | |
// | |
// let length = text.len(); | |
// | |
// forget(text); | |
// | |
// length | |
// } | |
fn main() -> Result<(), Box<dyn std::error::Error>> { | |
let mut store: Store<()> = Store::default(); | |
let module = Module::from_file( | |
store.engine(), | |
"./target/wasm32-unknown-unknown/debug/app.wasm", | |
)?; | |
let instance = Instance::new(&mut store, &module, &[])?; | |
let alloc = instance.get_typed_func::<i32, i32>(&mut store, "allocate_memory")?; | |
let hello_text = CString::new("Hello, dear world!")?; | |
let len = hello_text.as_bytes_with_nul().len() as i32; | |
// module_module_memory_ptr is a pointer to the memory allocated by the module. | |
// It is relative to the module's memory. | |
let allocated_ptr = alloc.call(&mut store, len)?; | |
dbg!(allocated_ptr as *mut u8); | |
let memory = instance | |
.get_memory(&mut store, "memory") | |
.ok_or("no memory")?; | |
// Write to memory by wasmtime API | |
memory | |
.write( | |
&mut store, | |
allocated_ptr as usize, | |
&hello_text.into_bytes_with_nul(), | |
) | |
.expect("write failed"); | |
// Mutate data in memory by Module function. | |
// This function will append " (FIN)" to the string. | |
// Starting pointer is the same as the one allocated by the module. | |
let add_end = instance.get_typed_func::<i32, i32>(&mut store, "add_end")?; | |
let new_len = add_end.call(&mut store, allocated_ptr)?; | |
// Read by Wasmtime API | |
let mut read_buf = vec![0_u8; new_len as usize]; | |
memory | |
.read(&store, allocated_ptr as usize, &mut read_buf) | |
.expect("read failed"); | |
assert_eq!(read_buf, b"Hello, dear world! (FIN)\0"); | |
// Write to memory by direct access to host memory | |
let base_ptr = memory.data_ptr(&store); | |
dbg!(base_ptr); | |
// offset_ptr is a pointer to the memory allocated by the module in host memory. | |
let offset_ptr = unsafe { base_ptr.add(allocated_ptr as usize) }; | |
dbg!(offset_ptr); | |
unsafe { | |
let new_string = CString::new("Hello, life!")?; | |
let len = new_string.as_bytes_with_nul().len(); | |
let new_string_ptr = new_string.as_bytes_with_nul().as_ptr(); | |
std::ptr::copy(new_string_ptr, offset_ptr, len); | |
} | |
// Mutate data in memory by Module function. | |
// There for us not interested length of the new string, | |
// because we read it as CString and it will be null terminated. | |
let _ = add_end.call(&mut store, offset_ptr as i32)?; | |
// Read by direct access to host memory | |
let result = unsafe { CString::from_raw(offset_ptr as *mut _) }; | |
assert_eq!(result.as_bytes_with_nul(), b"Hello, life! (FIN)\0"); | |
forget(result); | |
// Read all involved memory in examples to see "trash" after the string from first example | |
let mut read_buf = vec![0_u8; 28]; | |
memory | |
.read(&store, allocated_ptr as usize, &mut read_buf) | |
.expect("read failed"); | |
let read_buf = String::from_utf8(read_buf).expect("should be valid String"); | |
dbg!(&read_buf); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment