【问题标题】:Embed a wasm runtime into a standalone Rust app and allow wasm and host functions to call each other将 wasm 运行时嵌入到独立的 Rust 应用程序中,并允许 wasm 和宿主函数相互调用
【发布时间】:2023-02-10 10:51:34
【问题描述】:

是否可以像下面这样编写一个独立的 Rust 应用程序,将其编译成两部分,一个 wasm 和一个 native ,并将 wasm 运行时(如wasmtime)嵌入到最终的二进制文件中,整个部分就像一个应用程序一样工作?

WasmEdge 有一个标记 wasm 函数的宏 #[wasmedge_bindgen],但没有任何东西可以使主机函数在 wasm 运行时中可访问。

#[make_a_wasm_func]
fn f1(i: i32)->i32{
    i+1
}


#[make_a_host_func_that_can_be_called_from_wasm]
fn f2(i: i32)->i32{
    f1(i)+2
} 

#[make_a_wasm_func]
fn f3(i:i32)-> i32{
    f2(i)+3
}

fn main(){
    let r=f3(1);
    println!("{}",r);   

}

The expected output is 7.

【问题讨论】:

  • 我正在看一些非常相似的东西,我的理解是“主机”功能需要作为“导入对象”导入到“wasm”部分。我知道这可能不是您正在寻找的答案,但我认为我可能会添加更多背景信息。
  • WasmEdgethis repo 中发布了一系列示例。最近发布的示例涵盖了一些基本用例,例如如何从主机调用 wasm 库。对于您的用例,Example 2Example 2-1Example 4 可以帮助您。

标签: rust webassembly


【解决方案1】:

WasmEdge 的维护者在这里。希望以下示例代码可以帮助到您:

use wasmedge_sdk::{
    error::HostFuncError, host_function, params, Caller, ImportObjectBuilder, ValType, Vm, WasmVal,
    WasmValue,
};

#[host_function]
fn my_add(_caller: Caller, input: Vec<WasmValue>) -> Result<Vec<WasmValue>, HostFuncError> {
    // check the number of inputs
    if input.len() != 2 {
        return Err(HostFuncError::User(1));
    }

    // parse the first input of WebAssembly value type into Rust built-in value type
    let a = if input[0].ty() == ValType::I32 {
        input[0].to_i32()
    } else {
        return Err(HostFuncError::User(2));
    };

    // parse the second input of WebAssembly value type into Rust built-in value type
    let b = if input[1].ty() == ValType::I32 {
        input[1].to_i32()
    } else {
        return Err(HostFuncError::User(3));
    };

    let c = a + b;

    Ok(vec![WasmValue::from_i32(c)])
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // create an import module
    let import = ImportObjectBuilder::new()
        .with_func::<(i32, i32), i32>("add", my_add)?
        .build("extern")?;

    // create a new vm with default config and register the import module into the vm.
    let res = Vm::new(None)?.register_import_module(import)?.run_func(
        Some("extern"),
        "add",
        params!(15, 51),
    )?;

    println!("add({}, {}) = {}", 15, 51, res[0].to_i32());

    Ok(())
}

另外,在Cargo.toml添加如下依赖:

[dependencies]
wasmedge-sdk = "0.7.1"

【讨论】:

    猜你喜欢
    • 2020-02-29
    • 2020-10-27
    • 2023-01-16
    • 2022-01-25
    • 2020-01-22
    • 2021-03-22
    • 2020-08-20
    • 2022-11-02
    • 2021-03-12
    相关资源
    最近更新 更多