Wasmer升级后宿主函数如何访问内存?原wasmer_runtime实现受阻
在Wasmer中宿主函数访问内存的正确方式
从wasmer_runtime升级到Wasmer后,宿主函数确实无法再通过Ctx直接获取内存,核心解决思路是让自定义环境持有内存引用,根据内存的创建时机选择不同的初始化方式:
情况1:内存由Wasm模块自身定义(最常见场景)
这种场景下,Instance创建前内存尚未存在,需要用Option延迟初始化环境中的内存引用:
- 定义带内存引用的自定义环境
use wasmer::{Memory, MemoryView, Store, Instance, Module, imports, Function}; #[derive(Clone)] struct HostEnv { memory: Option<Memory>, }
- 编写宿主函数
函数接收&mut HostEnv作为第一个参数,访问内存前需确保引用已初始化:
fn host_fun(env: &mut HostEnv, index: u32) -> u8 { // 根据业务场景选择错误处理方式,这里用expect快速终止 let memory = env.memory.as_ref().expect("Host environment memory not initialized"); let view = memory.view::<u8>(); // 读取指定位置的内存数据 view[index as usize].read().unwrap() }
- 创建Instance并初始化环境内存
先初始化空内存的环境,生成导入对象,待Instance创建完成后再将内存注入环境:
let store = Store::default(); // 编译Wasm模块,示例用wat转wasm,实际可直接读取wasm文件 let module = Module::new(&store, wat2wasm(include_bytes!("your_module.wat"))).unwrap(); // 初始化环境,内存先设为None let mut env = HostEnv { memory: None }; // 构建导入对象,绑定宿主函数与环境 let import_object = imports! { "env" => { "host_fun" => Function::new_typed_with_env(&store, &mut env, host_fun), }, }; // 创建Instance let instance = Instance::new(&module, &import_object).unwrap(); // 将Instance中的内存引用赋值给环境 env.memory = Some(instance.exports.get_memory("memory").unwrap().clone());
情况2:内存由宿主侧导入给Wasm模块
如果内存是在宿主侧创建后导入给Wasm的,可直接在环境初始化时传入内存引用,无需Option:
- 定义环境并初始化内存
struct HostEnv { memory: Memory, } let store = Store::default(); // 创建符合Wasm模块要求的内存实例 let memory = Memory::new(&store, MemoryType::new(1, None, false)).unwrap(); let env = HostEnv { memory: memory.clone() };
- 构建导入对象并创建Instance
将内存与宿主函数一起导入Wasm模块:
let import_object = imports! { "env" => { "memory" => memory, "host_fun" => Function::new_typed_with_env(&store, env, host_fun), }, }; let instance = Instance::new(&module, &import_object).unwrap();
这种场景下,宿主函数可直接使用env.memory,无需额外初始化检查。
内容的提问来源于stack exchange,提问作者Markus Knecht
相关产品推荐
相关产品推荐

