0

Is it possible to write a standalone Rust app like the following, compile it into 2 parts, one wasm and one native , and embed a wasm runtime (like wasmtime) into the final binary and the whole piece just work like a single app?

WasmEdge has a macro #[wasmedge_bindgen] that marks a wasm func, but nothing that makes a host function accessible in wasm runtime though.

#[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.
2
  • I am looking at some thing very similar and my understanding is that "host" functions need to be imported into the "wasm" part as "import objects". I understand this is probably not the answer you are looking for but I thought that I might add a little more context. Commented Aug 29, 2022 at 16:52
  • WasmEdge published a series of examples in this repo. The examples in the recent release cover some basic use cases, such as how to call a wasm library from the host. For your use case, Example 2, Example 2-1 and Example 4 could help you. Commented Feb 9, 2023 at 10:39

1 Answer 1

2

Maintainer of WasmEdge here. Hope the following example code can help you:

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(())
}

In addition, add the following dependency in Cargo.toml:

[dependencies]
wasmedge-sdk = "0.7.1"
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.