WasmEdge Rust bindings 发布新版本,找 Bug 赢大奖

serverless 技术社区 2022-08-03 17:14:56

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

下图显示了 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 告诉我们。
...全文
197 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

217

社区成员

发帖
与我相关
我的任务
社区描述
Serverless 技术爱好者的聚集地
其他 企业社区
社区管理员
  • serverless 技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧