How can I use imported memory in Rust code targeting `wasm32-unknown-unknown`?

I have the following Rust code:

use wasmer::{
    imports, AsStoreRef, Function, FunctionEnv, FunctionEnvMut, Instance, Memory, MemoryType,
    Module, Store,
};

const WAT_CODE: &str = r#"
(module
    (import "env" "memory" (memory 1))
    (import "env" "log" (func $log (param i32 i32)))
    (data (i32.const 0) "Hello, World!")
    (func (export "printHello")
        (call $log (i32.const 0) (i32.const 13))
    )
)
"#;

pub fn main() -> anyhow::Result<()> {
    let mut store = Store::default();
    let module = Module::new(&store, WAT_CODE.bytes().collect::<Vec<_>>())?;
    let memory = Memory::new(&mut store, MemoryType::new(1, None, false))?;

    let env = FunctionEnv::new(&mut store, ());

    let memory_ref = memory.clone();
    let log_fn = Function::new_typed_with_env(
        &mut store,
        &env,
        move |env: FunctionEnvMut<()>, offset: i32, length: i32| {
            let mut data = vec![0; length as usize];
            memory_ref
                .view(&env.as_store_ref())
                .read(offset as u64, &mut data)
                .unwrap();
            println!("Log: {:?}", String::from_utf8(data).unwrap());
        },
    );

    let import_object = imports! {
        "env" => {
            "memory" => memory,
            "log" => log_fn,
        }
    };

    let instance = Instance::new(&mut store, &module, &import_object)?;

    let print_hello = instance.exports.get_function("printHello")?;
    print_hello.call(&mut store, &[])?;

    Ok(())
}

I want to subsitute the WAT code with a wasm module that is generated from Rust code. I have created a workspace with two packages runner-code and wasm-target-code.

In runner-code/src/main.rs:

use std::fs;
use wasmer::{imports, Instance, Memory, MemoryType, Module, Store, Value};

const WASM_BIN_FILE_PATH: &str = "target/wasm32-unknown-unknown/debug/wasm_target_code.wasm";

pub fn main() -> anyhow::Result<()> {
    let wasm_bin = fs::read(WASM_BIN_FILE_PATH)?;

    let mut store = Store::default();
    let module = Module::from_binary(&store, &wasm_bin)?;
    let memory = Memory::new(&mut store, MemoryType::new(1, None, false))?;

    let import_object = imports! {
        "env" => {
            "memory" => memory.clone(),
        }
    };

    let instance = Instance::new(&mut store, &module, &import_object)?;

    let print_hello = instance.exports.get_function("store_string")?;
    let Value::I32(offset) = (*print_hello.call(&mut store, &[])?)[0] else {
        panic!("store_string function did not return an i32 value");
    };

    let mut data = vec![0; 8];
    memory.view(&store).read(offset as u64, &mut data).unwrap();
    println!("Log: {:?}", String::from_utf8(data).unwrap());

    Ok(())
}

In wasm-target-code/src/lib.rs:

extern "C" {
    static mut IMPORTED_MEMORY: [u8; 65536];
}

fn store_string_in_imported_memory(s: &str) -> *mut u8 {
    unsafe {
        let ptr = IMPORTED_MEMORY.as_mut_ptr();
        ptr.copy_from(s.as_ptr(), s.len());
        ptr.add(s.len()).write(0); // Null-terminate the string
        ptr
    }
}

#[no_mangle]
pub extern "C" fn store_string() -> *mut u8 {
    store_string_in_imported_memory("John Doe")
}

Running cargo run after building wasm-target-code, the application fails with the error:

Error: RuntimeError: unreachable
    at std::panicking::rust_panic_with_hook::h6731baa78621a747 (wasm_target_code.wasm[39]:0x3073)
    at std::panicking::begin_panic_handler::{{closure}}::hb6cd8464ed39ae71 (wasm_target_code.wasm[29]:0x27f6)
    at std::sys_common::backtrace::__rust_end_short_backtrace::hbdf3ddeb21a1e747 (wasm_target_code.wasm[28]:0x2726)
    at rust_begin_unwind (wasm_target_code.wasm[34]:0x2d0d)
    at core::panicking::panic_nounwind_fmt::h6dbc36adcb815595 (wasm_target_code.wasm[54]:0x356b)
    at core::panicking::panic_nounwind::h16e38f5a9ff4ae2c (wasm_target_code.wasm[55]:0x35bf)
    at core::intrinsics::copy::precondition_check::hbeb9467e311fa9db (wasm_target_code.wasm[4]:0x4b7)
    at wasm_target_code::store_string_in_imported_memory::hc16b6d1a9cf40acc (wasm_target_code.wasm[0]:0x1c7)
    at store_string (wasm_target_code.wasm[1]:0x268)

How can I use imported memory in Rust code targeting wasm32-unknown-unknown?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.