使用操作系统服务

    WebAssembly 虚拟机是一个纯软件实现,它不具有生成随机数必须的硬件资源。这就是 WASI 为 WebAssembly 定义了一个从宿主操作系统获取一个随机种子的函数的原因。作为一个 Rust 开发者,你需要做的只是使用受欢迎的 rand 或者 getrandom 包。得益于 wasm32-wasi 编译器后端,这些包将在 WebAssembly 字节码中生成正确的 WASI 调用。如下是 Cargo.toml 中的依赖部分。

    [dependencies] rand = "0.7.3" getrandom = "0.1.14"

    如下是在 WebAssembly 生成随机数的 Rust 代码。

    从 Rust 中输出和调试

    Rust 中的 println! 宏同样可以用在 WASI 中。下面的语句向运行 WasmEdge 的进程的 STDOUT 输出。

    1. #![allow(unused)]
    2. fn main() {
    3. pub fn echo(content: &str) -> String {
    4. println!("Printed from wasi: {}", content);
    5. return content.to_string();
    6. }
    7. }

    读写文件

    WASI 让你可以通过标准的 Rust std::fs 接口来访问宿主的文件系统。 在 Rust 程序中,你通过相对路径来操作文件,相对路径的根目录可以在启动 WasmEdge Runtime 的时候被指定。

    1. #![allow(unused)]
    2. fn main() {
    3. use std::fs;
    4. use std::fs::File;
    5. use std::io::{Write, Read};
    6. pub fn create_file(path: &str, content: &str) {
    7. let mut output = File::create(path).unwrap();
    8. output.write_all(content.as_bytes()).unwrap();
    9. }
    10. pub fn read_file(path: &str) -> String {
    11. let mut f = File::open(path).unwrap();
    12. let mut s = String::new();
    13. match f.read_to_string(&mut s) {
    14. Ok(_) => s,
    15. Err(e) => e.to_string(),
    16. }
    17. }
    18. pub fn del_file(path: &str) {
    19. fs::remove_file(path).expect("Unable to delete");
    20. }
    21. }

    包含 main() 函数的 Rust 程序可以被编译为一个独立的 WebAssembly 程序。

    使用如下的命令来编译 。

    cargo build --target wasm32-wasi

    $ wasmedge --dir .:. target/wasm32-wasi/debug/wasi.wasm hello Random number: -68634548 Random bytes: [87, 117, 194, 122, 74, 189, 29, 1, 113, 26, 90, 6, 151, 20, 11, 169, 131, 212, 161, 220, 216, 190, 77, 234, 30, 10, 159, 7, 14, 89, 81, 111, 247, 136, 39, 195, 83, 90, 153, 225, 66, 16, 150, 217, 137, 172, 216, 203, 251, 37, 4, 27, 32, 57, 76, 237, 99, 147, 24, 175, 208, 157, 3, 220, 46, 224, 199, 153, 144, 96, 120, 89, 160, 38, 171, 239, 87, 218, 41, 184, 220, 78, 157, 57, 229, 198, 222, 72, 219, 118, 237, 27, 229, 28, 51, 116, 88, 101, 40, 139, 160, 51, 156, 102, 66, 233, 101, 50, 131, 9, 253, 186, 73, 148, 85, 36, 155, 254, 168, 202, 23, 96, 181, 99, 120, 136, 28, 147] This is from a main function The env vars are as follows. ... ... The args are as follows. target/wasm32-wasi/debug/wasi.wasm hello File content is This is in a file

    正如我们之前看到的,你可以在 Rust lib.rs 中创建 WebAssembly 函数。在这些函数中,你同样可以使用 WASI 函数。然而,需要注意的是,没有 函数的情况下,你将会需要显式地调用一个辅助函数来初始化环境,以此让 WASI 函数正常工作。 在 Cargo.toml 中添加一个辅助包,这样的话 WASI 初始化代码将会应用在你导出的的公开库函数上。

    [dependencies] ... ... wasmedge-wasi-helper = "=0.2.0"

    在访问任何参数和环境变量或者操作任何文件之前,我们需要调用 _initialize() 函数。

    1. #![allow(unused)]
    2. pub fn print_env() -> i32 {
    3. _initialize();
    4. ... ...
    5. }
    6. pub fn create_file(path: &str, content: &str) -> String {
    7. _initialize();
    8. ... ...
    9. }
    10. pub fn read_file(path: &str) -> String {
    11. _initialize();
    12. ... ...
    13. }
    14. pub fn del_file(path: &str) -> String {
    15. _initialize();
    16. ... ...
    17. }
    18. }