如何使用 wasmer-wasi 从 Rust 中的 WASM 读取现有目录?
How can I read an existing directory from WASM in Rust using wasmer-wasi?
我写了一个简单的 wasmer-wasi 示例来读取目录条目,但它总是失败。
#[no_mangle]
pub fn start() {
std::fs::read_dir("/").unwrap();
}
use wasmer::{Instance, Module, Store};
use wasmer_wasi::WasiState;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let wasm = std::fs::read("target/wasm32-wasi/debug/wasi_fs_example.wasm")?;
let store = Store::default();
let module = Module::new(&store, wasm)?;
let mut wasi_env = WasiState::new("wasi_fs_example")
.preopen_dir("target")?
.finalize()?;
let import_object = wasi_env.import_object(&module)?;
let instance = Instance::new(&module, &import_object)?;
let start = instance.exports.get_function("start")?;
start.call(&[])?;
Ok(())
}
这会在 运行:
时产生错误
cargo build -p wasi_fs_example --target wasm32-wasi
cargo run -p runner
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "failed to find a pre-opened file descriptor through which \"/\" could be opened" }', wasi_fs_example/src/lib.rs:6:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
示例的完整源代码位于 here。为什么它不起作用?
目前在 Rust 中我们真的只能创建 WASI 二进制文件,不能创建库。 WASI 仅在需要存在的主要功能期间有效。从其他任何地方调用 wasi 函数会出现段错误,因为 libpreopen 未初始化。
总结一下,目前如何解决这个问题:
- 根本没有
lib.crate-type
- 让文件成为
src/main.rs
,而不是 src/lib.rs
- 在
src/main.rs
的顶部有 #![no_main]
- 使用
RUSTFLAGS="-Z wasi-exec-model=reactor" cargo +nightly build --target wasm32-wasi
- 确保先调用
_initialize
https://github.com/WebAssembly/WASI/issues/24
https://github.com/rust-lang/rust/pull/79997
就我而言:
#![no_main]
#[no_mangle]
pub extern "C" fn start() {
std::fs::read_dir("/").unwrap();
}
...
let start = instance.exports.get_function("_initialize")?;
start.call(&[])?;
let start = instance.exports.get_function("start")?;
start.call(&[])?;
...
RUSTFLAGS="-Z wasi-exec-model=reactor" cargo +nightly build -p wasi_fs_example --target wasm32-wasi
我写了一个简单的 wasmer-wasi 示例来读取目录条目,但它总是失败。
#[no_mangle]
pub fn start() {
std::fs::read_dir("/").unwrap();
}
use wasmer::{Instance, Module, Store};
use wasmer_wasi::WasiState;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let wasm = std::fs::read("target/wasm32-wasi/debug/wasi_fs_example.wasm")?;
let store = Store::default();
let module = Module::new(&store, wasm)?;
let mut wasi_env = WasiState::new("wasi_fs_example")
.preopen_dir("target")?
.finalize()?;
let import_object = wasi_env.import_object(&module)?;
let instance = Instance::new(&module, &import_object)?;
let start = instance.exports.get_function("start")?;
start.call(&[])?;
Ok(())
}
这会在 运行:
时产生错误cargo build -p wasi_fs_example --target wasm32-wasi
cargo run -p runner
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "failed to find a pre-opened file descriptor through which \"/\" could be opened" }', wasi_fs_example/src/lib.rs:6:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
示例的完整源代码位于 here。为什么它不起作用?
目前在 Rust 中我们真的只能创建 WASI 二进制文件,不能创建库。 WASI 仅在需要存在的主要功能期间有效。从其他任何地方调用 wasi 函数会出现段错误,因为 libpreopen 未初始化。
总结一下,目前如何解决这个问题:
- 根本没有
lib.crate-type
- 让文件成为
src/main.rs
,而不是src/lib.rs
- 在
src/main.rs
的顶部有 - 使用
RUSTFLAGS="-Z wasi-exec-model=reactor" cargo +nightly build --target wasm32-wasi
- 确保先调用
_initialize
#![no_main]
https://github.com/WebAssembly/WASI/issues/24
https://github.com/rust-lang/rust/pull/79997
就我而言:
#![no_main]
#[no_mangle]
pub extern "C" fn start() {
std::fs::read_dir("/").unwrap();
}
...
let start = instance.exports.get_function("_initialize")?;
start.call(&[])?;
let start = instance.exports.get_function("start")?;
start.call(&[])?;
...
RUSTFLAGS="-Z wasi-exec-model=reactor" cargo +nightly build -p wasi_fs_example --target wasm32-wasi