Introduction to WasmEdge module instance
Overview
In this section, we will talk about module instance. In wasmedge-sys crate, four kinds of module instances are defined:
-
Instance -
An
Instancerepresents a runtime module instance which is held by a WasmEdgeStorecontext. TheStorecontext is either held by a WasmEdgeVm, or related to a WasmEdgeExecutor. -
APIs to retrieve an
Instance.-
If a
Vmis available, then -
with the
Vm::active_moduleAPI, you can get an anonymous module instance from thisVm. - with the
Vm::store_mutandStore::moduleAPIs, you can get a named module instance from thisVm. -
If an
Executoris available, then -
with the
Executor::register_named_moduleAPI, you can get a named module instance from thisExecutor. - with the
Executor::register_active_moduleAPI, you can get an anonymous module instance from thisExecutor. ImportModule
-
-
ImportModule, also called import module, represents a module instance to be registered into a WasmEdgeVmorExecutor.ImportModuleimplements theImportObjecttrait, meaning that WebAssembly function, table, memory and global instances can be added to an import module, and then be registered and instantiated together when the import module is registered into aVmorExecutor. -
WasiModuleandWasmEdgeProcessModule -
WasiModuleandWasmEdgeProcessModuleare module instances for WASI and WasmEdgeProcess specification, respectively. They also implement theImportObjecttrait. Different fromImportModule, these two kinds of module instances can not only be created, but be retrieved from aVm. -
APIs to retrieve
WasiModuleandWasmEdgeProcessModule.-
If a
Vmis available, then -
with the
Vm::wasi_moduleAPI, you can get a module instance ofWasiModuletype. - with the
Vm::wasmedge_process_moduleAPI, you can get aWasmEdgeProcessModulefrom thisVm.
-
Examples
Example 1
In this example, we’ll demonstrate how to use the APIs of Vm to
- Create Wasi and WasmEdgeProcess module instances implicitly by using a
Configwhile creating aVm.
``` 2. #![allow(unused)]
- fn main() {
- // create a Config context
- let mut config = Config::create()?;
- config.bulk_memory_operations(true);
- assert!(config.bulk_memory_operations_enabled());
- config.wasi(true);
- assert!(config.wasi_enabled());
- config.wasmedge_process(true);
-
assert!(config.wasmedge_process_enabled());
-
// create a Vm context with the given Config and Store
-
let mut vm = Vm::create(Some(config), None)?;
-
} ```
- Retrieve the Wasi and WasmEdgeProcess module instances from the
Vm.
``` 2. #![allow(unused)]
- fn main() {
- // get the default Wasi module
- let wasi_instance = vm.wasi_module_mut()?;
- assert_eq!(wasi_instance.name(), "wasi_snapshot_preview1");
- // get the default WasmEdgeProcess module instance
- let wasmedge_process_instance = vm.wasmedge_process_module_mut()?;
-
assert_eq!(wasmedge_process_instance.name(), "wasmedge_process");
-
} ```
- Register an import module as a named module into the
Vm.
``` 2. #![allow(unused)]
- fn main() {
- // create ImportModule instance
- let module_name = "extern_module";
-
let mut import = ImportModule::create(module_name)?;
-
// a function to import
- fn real_add(inputs: Vec
) -> Result<Vec , u8> { - if inputs.len() != 2 {
- return Err(1);
-
}
-
let a = if inputs[0].ty() == ValType::I32 {
- inputs[0].to_i32()
- } else {
- return Err(2);
-
};
-
let b = if inputs[1].ty() == ValType::I32 {
- inputs[1].to_i32()
- } else {
- return Err(3);
-
};
-
let c = a + b;
-
Ok(vec![WasmValue::from_i32(c)])
-
}
-
// add host function
- let func_ty = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32])?;
- let host_func = Function::create(&func_ty, Box::new(real_add), 0)?;
-
import.add_func("add", host_func);
-
// add table
- let table_ty = TableType::create(RefType::FuncRef, 0..=u32::MAX)?;
- let table = Table::create(&table_ty)?;
-
import.add_table("table", table);
-
// add memory
- let mem_ty = MemType::create(0..=u32::MAX)?;
- let memory = Memory::create(&mem_ty)?;
-
import.add_memory("mem", memory);
-
// add global
- let ty = GlobalType::create(ValType::F32, Mutability::Const)?;
- let global = Global::create(&ty, WasmValue::from_f32(3.5))?;
-
import.add_global("global", global);
-
// register the import module as a named module
-
vm.register_wasm_from_import(ImportObject::Import(import))?;
-
} ```
- Retrieve the internal
Storeinstance from theVm, and retrieve the named module instance from theStoreinstance.
``` 2. #![allow(unused)]
- fn main() {
- let mut store = vm.store_mut()?;
- let named_instance = store.module(module_name)?;
- assert!(named_instance.get_func("add").is_ok());
- assert!(named_instance.get_table("table").is_ok());
- assert!(named_instance.get_memory("mem").is_ok());
-
assert!(named_instance.get_global("global").is_ok());
-
} ```
- Register an active module into the
Vm.
``` 2. #![allow(unused)]
- fn main() {
- // read the wasm bytes
- let wasm_bytes = wat2wasm(
- br#"
- (module
- (export "fib" (func $fib))
- (func $fib (param $n i32) (result i32)
- (if
- (i32.lt_s
- (get_local $n)
- (i32.const 2)
- )
- (return
- (i32.const 1)
- )
- )
- (return
- (i32.add
- (call $fib
- (i32.sub
- (get_local $n)
- (i32.const 2)
- )
- )
- (call $fib
- (i32.sub
- (get_local $n)
- (i32.const 1)
- )
- )
- )
- )
- )
- )
- "#,
-
)?;
-
// load a wasm module from a in-memory bytes, and the loaded wasm module works as an anoymous
- // module (aka. active module in WasmEdge terminology)
-
vm.load_wasm_from_bytes(&wasm_bytes)?;
-
// validate the loaded active module
-
vm.validate()?;
-
// instatiate the loaded active module
-
vm.instantiate()?;
-
// get the active module instance
- let active_instance = vm.active_module()?;
-
assert!(active_instance.get_func("fib").is_ok());
-
} ```
- Retrieve the active module from the
Vm.
``` 2. #![allow(unused)]
- fn main() {
- // get the active module instance
- let active_instance = vm.active_module()?;
-
assert!(active_instance.get_func("fib").is_ok());
-
} ```
The complete code in this demo can be found on WasmEdge Github.
Example 2
In this example, we’ll demonstrate how to use the APIs of Executor to
- Create an
Executorand aStore.
``` 2. #![allow(unused)]
- fn main() {
- // create an Executor context
-
let mut executor = Executor::create(None, None)?;
-
// create a Store context
-
let mut store = Store::create()?;
-
} ```
- Register an import module into the
Executor.
``` 2. #![allow(unused)]
- fn main() {
- // read the wasm bytes
- let wasm_bytes = wat2wasm(
- br#"
- (module
- (export "fib" (func $fib))
- (func $fib (param $n i32) (result i32)
- (if
- (i32.lt_s
- (get_local $n)
- (i32.const 2)
- )
- (return
- (i32.const 1)
- )
- )
- (return
- (i32.add
- (call $fib
- (i32.sub
- (get_local $n)
- (i32.const 2)
- )
- )
- (call $fib
- (i32.sub
- (get_local $n)
- (i32.const 1)
- )
- )
- )
- )
- )
- )
- "#,
-
)?;
-
// load module from a wasm file
- let config = Config::create()?;
- let loader = Loader::create(Some(config))?;
-
let module = loader.from_bytes(&wasm_bytes)?;
-
// validate module
- let config = Config::create()?;
- let validator = Validator::create(Some(config))?;
-
validator.validate(&module)?;
-
// register a wasm module into the store context
- let module_name = "extern";
- let named_instance = executor.register_named_module(&mut store, &module, module_name)?;
-
assert!(named_instance.get_func("fib").is_ok());
-
} ```
- Register an active module into the
Executor.
``` 2. #![allow(unused)]
- fn main() {
- // read the wasm bytes
- let wasm_bytes = wat2wasm(
- br#"
- (module
- (export "fib" (func $fib))
- (func $fib (param $n i32) (result i32)
- (if
- (i32.lt_s
- (get_local $n)
- (i32.const 2)
- )
- (return
- (i32.const 1)
- )
- )
- (return
- (i32.add
- (call $fib
- (i32.sub
- (get_local $n)
- (i32.const 2)
- )
- )
- (call $fib
- (i32.sub
- (get_local $n)
- (i32.const 1)
- )
- )
- )
- )
- )
- )
- "#,
-
)?;
-
// load module from a wasm file
- let config = Config::create()?;
- let loader = Loader::create(Some(config))?;
-
let module = loader.from_bytes(&wasm_bytes)?;
-
// validate module
- let config = Config::create()?;
- let validator = Validator::create(Some(config))?;
-
validator.validate(&module)?;
-
// register a wasm module as an active module
- let active_instance = executor.register_active_module(&mut store, &module)?;
-
assert!(active_instance.get_func("fib").is_ok());
-
} ```
The complete code in this demo can be found on WasmEdge Github.
