Stream: wasmtime

Topic: wasmtime API: Using imported memory from imported function


view this post on Zulip Manuel Ceron (Jun 14 2024 at 10:36):

Hi, I hope this is the right place for beginner questions about the wasmtime API in Rust. I want to run a simple Wasm "hello world" module copied from Mozilla's documentation. The module imports a memory and a "console.log" function. I want to run it with wasmtime. My rust program looks like this:

use wasmtime::*;

fn main() -> Result<()> {
    let code = r#"
        (module
          (import "console" "log" (func $log (param i32 i32)))
          (import "js" "mem" (memory 1))
          (data (i32.const 0) "Hi")
          (func (export "writeHi")
            i32.const 0  ;; pass offset 0 to log
            i32.const 2  ;; pass length 2 to log
            call $log
          )
        )
    "#;

    let engine = Engine::default();
    let module = Module::new(&engine, code)?;
    let mut store = Store::new(&engine, ());
    let memory = Memory::new(&mut store, MemoryType::new(1, None))?;

    let console_log = Func::wrap(&mut store, |mut caller: Caller<'_, ()>, ptr: i32, len: i32| {
        let message = // How can I access the imported memory from here???
        println!("{}", message);
        Ok(())
    });

    let imports = [console_log.into(), memory.into()];
    let instance = Instance::new(&mut store, &module, &imports)?;

    let run = instance.get_typed_func::<(), ()>(&mut store, "writeHi")?;
    run.call(&mut store, ())?;
    Ok(())
}

So I want my console_log function to read the memory that is imported by the module at the given offset + lenght and print it to the stdout. But how can I do that?

I've seen an example that uses caller.get_export() to get a memory that is exported from the Wasm module to the host. But in this case the memory is defined in the host and imported into the module.

And I can't move memory into the wrapped lambda because I won't be able to pass it to the instance later.

Thanks in advance for the help!

view this post on Zulip Lann Martin (Jun 14 2024 at 13:17):

I haven't tried this specifically, but I believe the answer is that Memory is just a handle to the imported memory in the Store. You should be able to clone that handle, pass the copy into your Func::wrap closure, and access the memory buffer via e.g. Memory::data.

view this post on Zulip Manuel Ceron (Jun 14 2024 at 14:02):

Yes, cloning and moving into the closure works as expected. Thanks!


Last updated: Dec 23 2024 at 13:07 UTC