WasmEdge Rust SDK 发布新版本

伴随着 WasmEdge 0.10.1 发布,WasmEdge Rust bindings 的全新版本也闪亮登场:wasmedge-sdk v0.2.0wasmedge-sys v0.8.0。 你可以在 这里 找到相关 API 文档和源代码。

下图显示了 WasmEdge Rust bindings 的架构。 wasmedge-sys crate 定义了一组低级 Rust API,它们简单地包了 WasmEdge C-API 并提供相应的安全版本,而 wasmedge-sdk 定义了一组围绕应用程序的高级 Rust API。

我们建议大多数应用程序开发者使用 wasmedge-sdk crate。 因此,本文将重点介绍 wasmedge-sdk。 如果对 WasmEdge 低级 Rust API 的内部情况感兴趣,请可以查看wasmedge-sys 源代码

WasmEdge Rust bindings SDK 使 Rust 应用程序能够嵌入 WebAssembly 函数或模块。 这对于基于 Rust 的云原生或区块链基础设施软件特别有用,因为它们需要以安全有效的方式支持不受信任的用户函数。

wasmedge-sdk crate 的主要设计目标是使开发者能够使用 WasmEdge 轻松安全地将第三方代码合并到他们的 rust 应用程序中。 wasmedge-sdk crate 旨在为 Rust 开发者提供顺滑的体验。

下面让我们来看一个简单的例子吧!

wasmedge-sdk 开始

这个例子展示了如何从 Rust 程序运行 WasmEdge host 函数。 该函数也是用 Rust 编写的。 你也可以使用 C、TinyGo 或 JavaScript 等编程语言编写 WasmEdge 函数。

这里我们使用一个简单的 hello world 程序来解释 wasmedge-sdk 是如何工作的。 此示例演示了如何完成以下工作。

1.通过ImportObjectBuilder 加载第三方 native 函数 2.加载 native 函数生成的 Wasm 模块

有关 wasmedge-sdk 的更多示例,请查看此处

首先,确保已经在本地系统上安装了 Rust 和 WasmEdge。 如果想使用 WasmEdge 的 WasmEdgeProcess 插件,请注意 Linux 是唯一支持的操作系统。

接下来,从 WasmEdge repo 中获取 wasmedge-sdk 示例。

$ git clone https://github.com/WasmEdge/WasmEdge.git
$ cd /bindings/rust/

然后,使用下面的命令行从 wasmedge-sdk 文件运行 hello world 示例。

cargo run -p wamedge-sdk --example hello_world -- --nocapture

如果命令行成功运行,会看到 Hello, world! 在终端中打印出来,如下图所示。

现在让我们深入研究代码。 上述 Hello World 示例的源代码可以在这里找到。

让我们立即获取所有 imports 并开始:

// 如果使用 < 1.63 版本的 rust,请添加此特性
// #![feature(explicit_generic_args_with_impl_trait)]

use wasmedge_sdk::{params, Executor, ImportObjectBuilder, Module, Store};
use wasmedge_sys::WasmValue;
use wasmedge_types::wat2wasm;

定义一个 native 函数并创建一个 ImportObject

首先,让我们定义一个名为 say_hello_world 的 native 函数,它会打印出 Hello, World!

fn say_hello_world(_inputs: Vec<WasmValue>) -> Result<Vec<WasmValue>, u8> {
    println!("Hello, world!");

    Ok(vec![])
}

要在 WasmEdge runtime 中使用 native 函数作为 import 函数,我们需要一个 ImportObjectwasmedge-sdk 定义了一个 ImportObjectBuilder,它提供了一组用于创建 ImportObject 的 chaining 方法。我们看看具体方法:

// 创建一个 import 模块
let import = ImportObjectBuilder::new()
    .with_func::<(), ()>("say_hello", say_hello_world)?
    .build("env")?; 

现在,我们有一个名为 env 的 import 模块,它包含一个 host 函数 say_hello。 也许你注意到,我们用于 import 模块和 host 函数的名称与 Wasm 模块中出现的名称完全相同。 可以在下一节中找到 Wasm 模块。

加载一个 wasm 模块

现在我们加载一个 Wasm 模块。 wasmedge-sdkModule 中定义了两个方法:

  • from_file 从文件加载一个 Wasm 模块,并且同时验证已经加载的模块。

  • from_bytes 从内存字节数组中加载一个 Wasm 模块,同时验证加载的 Wasm 模块。

这里我们选择使用 Module::from_bytes 方法从内存字节数组中加载我们的 Wasm 模块。

let wasm_bytes = wat2wasm(
    br#"
(module
    ;; First we define a type with no parameters and no results.
    (type $no_args_no_rets_t (func (param) (result)))

    ;; Then we declare that we want to import a function named "env" "say_hello" with
    ;; that type signature.
    (import "env" "say_hello" (func $say_hello (type $no_args_no_rets_t)))

    ;; Finally we create an entrypoint that calls our imported function.
    (func $run (type $no_args_no_rets_t)
    (call $say_hello))
    ;; And mark it as an exported function named "run".
    (export "run" (func $run)))
"#,
)?;

// 从给定的内存字节加载一个 Wasm 模块并返回一个编译的模块
let module = Module::from_bytes(None, &wasm_bytes)?;

注册 import 模块和编译模块

要注册一个已编译的模块,我们需要检查它是否依赖于某些 import 模块。 在 Wasm 模块中,这条语句 (import "env" "say_hello" (func $say_hello (type $no_args_no_rets_t))) 告诉我们,它依赖于一个名为 env 的 import 模块。 因此,在注册编译好的 wasm 模块之前,我们需要先注册 import 模块。

// 创建一个 executor
let mut executor = Executor::new(None, None)?;

// 创一个 store 
let mut store = Store::new()?;

// 将 import 模块注册到 store 中
store.register_import_module(&mut executor, &import)?;

// 将编译好的模块注册到 store 中,并得到一个模块实例
let extern_instance = store.register_named_module(&mut executor, "extern", &module)?;

在上面的代码中我们使用 ExecutorStore 来注册 import 模块和已编译模块。wasmedge-sdk 也提供其它 APIs 来做同样的工作: Vm::register_import_moduleVm::register_module_from_bytes

运行导出的函数

现在可以运行导出的函数。

// 获取导出的函数 "run"
let run = extern_instance
    .func("run")
    .ok_or_else(|| anyhow::Error::msg("Not found exported function named 'run'."))?;

// 运行 host 函数
run.call(&mut executor, params!())?;

展望未来

很快,wasmedge-sdk 将添加对嵌入式 Wasm 和异步 host 函数的异步调用的支持。 另一个重要特性是支持 wasmedge-sdk 中的复杂接口类型,允许开发者将复杂的数据结构(如字符串和用户定义的复杂类型)传递给 Wasm VM。

为 wasmedge-sdk 的开发做贡献

wasmedge-sdk 还在开发中,期待社区的反馈。 下面是需要社区小伙伴帮助的类目。此外,针对每一次反馈,我们会寄出礼物作为感谢。在这里查看规则

  • 试试 wasmedge-sdk,让我们知道如何改进。 此外,如果有任何问题,请提 issue
  • Bug 报告。 不可避免地,有一些我们没有涵盖的边缘测试用例。 如果发现新的 bug,请随时提出 issue 并告诉我们。
  • 查看文档。 文档对于开源软件来说是必不可少的。 如果发现文档有问题,请不要犹豫提 issue 或创建 PR 来修正。
  • 提出功能需求。 wasmedge-sdk 目前的特性来自我们用户的真实需求。 如果你有想到好的主意,请通过 issue 告诉我们。
{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/4532842/blog/5561744