You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在目标为wasm32-unknown-unknown的Rust代码中使用导入内存?

在Rust wasm32-unknown-unknown目标中正确使用导入内存的问题

原本通过WAT结合Wasmer实现了导入内存的使用,现替换为Rust生成Wasm模块,创建了包含runner-code和wasm-target-code的工作空间:

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(())
}

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")
}

构建wasm-target-code后运行cargo run,出现以下错误:

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)

解决方案

1. 修正导入内存的声明方式

Rust中直接声明固定大小数组的方式不符合Wasm内存导入规范,Wasm内存是通过memory导入项提供的,需改用#[link(wasm_import_module = "env")]标记导入的内存指针:

修改wasm-target-code/src/lib.rs:

#[link(wasm_import_module = "env")]
extern "C" {
    static mut memory: *mut u8;
}

fn store_string_in_imported_memory(s: &str) -> *mut u8 {
    unsafe {
        let ptr = memory;
        ptr.copy_from(s.as_ptr(), s.len());
        ptr.add(s.len()).write(0);
        ptr
    }
}

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

2. 优化内存访问安全性(推荐)

直接从内存起始位置写入可能覆盖Wasm模块自身数据,建议使用Rust的内存分配器预留安全区域:

首先在wasm-target-code/Cargo.toml添加依赖:

[dependencies]
alloc = { version = "0.2", features = ["global"] }

然后修改代码:

#[link(wasm_import_module = "env")]
extern "C" {
    static mut memory: *mut u8;
}

fn store_string_in_imported_memory(s: &str) -> *mut u8 {
    unsafe {
        let mut buf = Vec::with_capacity(s.len() + 1);
        buf.extend_from_slice(s.as_bytes());
        buf.push(0);
        let ptr = buf.as_mut_ptr();
        std::mem::forget(buf);
        ptr
    }
}

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

3. 调整宿主端内存配置

若使用堆分配,需允许内存扩容,修改runner-code/src/main.rs的内存创建代码:

// 允许内存扩容至16页(每页64KB)
let memory = Memory::new(&mut store, MemoryType::new(1, Some(16), false))?;

4. 配置Wasm模块构建参数

在wasm-target-code/Cargo.toml添加以下配置,确保编译为符合要求的Wasm文件:

[profile.dev]
panic = "abort"

[lib]
crate-type = ["cdylib"]

执行构建命令:

cd wasm-target-code
cargo build --target wasm32-unknown-unknown

内容的提问来源于stack exchange,提问作者Archy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:55:10