Project: WasmEdge Runtime (Runtime / Container Runtime)
File: table_and_funcref.md

In this example, we'll present how to use and stored in a slot of a `Table` instance to implement indirect function invocation. The code in the following example is verified on wasmedge-sdk v0.5.0 wasmedge-sys v0.10.0 wasmedge-types v0.3.0 Let's start off by getting all imports right away so you can follow along ```rust // If the version of rust used is less than v1.63, please uncomment the follow attribute. // #![feature(explicitgenericargswithimpl_trait)] use wasmedge_sdk::{ config::{CommonConfigOptions, ConfigBuilder}, error::HostFuncError, host_function, params, types::Val, Caller, Executor, Func, ImportObjectBuilder, RefType, Store, Table, TableType, ValType, WasmVal, WasmValue, }; ``` In this example we defines a native function `real_add` that takes two numbers and returns their sum. This function will be registered as a host function into WasmEdge runtime environment ```rust fn realadd(caller: &Caller, input: Vec<WasmValue>) -> Result<Vec<WasmValue>, HostFuncError> { println!("Rust: Entering Rust function real_add"); if input.len() != 2 { return Err(HostFuncError::User(1)); } let a = if input[0].ty() == ValType::I32 { input[0].to_i32() } else { return Err(HostFuncError::User(2)); }; let b = if input[1].ty() == ValType::I32 { input[1].to_i32() } else { return Err(HostFuncError::User(3)); }; let c = a + b; println!("Rust: calculating in real_add c: {:?}", c); println!("Rust: Leaving Rust function real_add"); Ok(vec![WasmValue::from_i32(c)]) } ``` The first thing we need to do is to create a `Table` instance. After that, we register the table instance along with an import module into the WasmEdge runtime environment. Now let's see the code. ```rust // create an executor let config = ConfigBuilder::new(CommonConfigOptions::default()).build()?; let mut executor = Executor::new(Some(&config), None)?; // create a store let mut store = Store::new()?; // create a table instance let result = Table::new(TableType::new(RefType::FuncRef, 10, Some(20))); assert!(result.is_ok()); let table = result.unwrap(); // create an import object let import = ImportObjectBuilder::new() .with_table("my-table", table)? .build("extern")?; // register the import object into the store store.registerimportmodule(&mut executor, &import)?; ``` In the code snippet above, we create a `Table` instance with the initial size of `10` and the maximum size of 20. The element type of the `Table` instance is `reference to function`. In the previous steps, we defined a native function `realadd` and registered a `Table` instance named `my-table` into the runtime environment. Now we'll save a reference to `readadd` function to a slot of `my-table`. ```rust // get the imported module instance let instance = store .module_instance("extern") .expect("Not found module instance named 'extern'"); // get the exported table instance let mut table = instance .table("my-table") .expect("Not found table instance named 'my-table'"); // create a host function let hostfunc = Func::wrap::<(i32, i32), i32, !>(Box::new(realadd), None)?; // store the reference to host_func at the given index of the table instance table.set(3, Val::FuncRef(Some(hostfunc.asref())))?; ``` We save the reference to `host_func` into the third slot of `my-table`. Next, we can retrieve the function reference from the table instance by index and call the function via its reference. ```rust // retrieve the function reference at the given index of the table instance let value = table.get(3)?; if let Val::FuncRef(Some(func_ref)) = value { // get the function type by func_ref let functy = funcref.ty()?; // arguments asserteq!(functy.args_len(), 2); let paramtys = functy.args().unwrap(); asserteq!(paramtys, [ValType::I32, ValType::I32]); // returns asserteq!(functy.returns_len(), 1); let returntys = functy.returns().unwrap(); asserteq!(returntys, [ValType::I32]); // call the function by func_ref let returns = func_ref.call(&mut executor, params!(1, 2))?; assert_eq!(returns.len(), 1); asserteq!(returns[0].toi32(), 3); } ``` The complete code of this example can be found in .