summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2025-01-14 17:41:29 +0100
committerHenry Gressmann <mail@henrygressmann.de>2025-01-14 17:41:29 +0100
commit40e570cf8bdd948c1e7e9dd85e5ac24d9a062d2a (patch)
tree64e9338f1c656fd9d81f51cd4f425359b2dbc6d1 /examples
parent1a64f4092af9304694e98f441b79f0a93ee1c194 (diff)
chore: update deps, spelling
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'examples')
-rw-r--r--examples/archive.rs6
-rw-r--r--examples/funcref_callbacks.rs101
-rw-r--r--examples/linking.rs9
-rw-r--r--examples/wasm-rust.rs3
4 files changed, 67 insertions, 52 deletions
diff --git a/examples/archive.rs b/examples/archive.rs
index ea82c51..f1a19b6 100644
--- a/examples/archive.rs
+++ b/examples/archive.rs
@@ -11,12 +11,12 @@ const WASM: &str = r#"
"#;
fn main() -> Result<()> {
- let wasm = wat::parse_str(WASM).expect("failed to parse wat");
+ let wasm = wat::parse_str(WASM).expect("Failed to parse WAT");
let module = Parser::default().parse_module_bytes(wasm)?;
let twasm = module.serialize_twasm();
- // now, you could e.g. write twasm to a file called `add.twasm`
- // and load it later in a different program
+ // Now, you could e.g. write `twasm` to a file called `add.twasm`
+ // and load it later in a different program.
let module: Module = TinyWasmModule::from_twasm(&twasm)?.into();
let mut store = Store::default();
diff --git a/examples/funcref_callbacks.rs b/examples/funcref_callbacks.rs
index 08332cb..df50e75 100644
--- a/examples/funcref_callbacks.rs
+++ b/examples/funcref_callbacks.rs
@@ -1,6 +1,5 @@
use eyre::Result;
use tinywasm::{types::FuncRef, Extern, FuncContext, Imports, Module, Store};
-use wat;
fn main() -> Result<()> {
by_func_ref_passed()?;
@@ -8,30 +7,30 @@ fn main() -> Result<()> {
Ok(())
}
-/// example of passing wasm functions (as funcref) to imported host function
-/// and imported host function calling them
+/// Example of passing Wasm functions (as `funcref`) to an imported host function
+/// and the imported host function calling them.
fn by_func_ref_passed() -> Result<()> {
- // a module with:
- // imported function "host.call_this" that accepts a callback
- // exported wasm function "tell_host_to_call" that calls "host.call_this" with wasm functions $add and $sub
- // wasm functions $add and $sub and imported function $mul used as callbacks
- // (just to show that imported functions can be referenced too)
- // exported wasm function "call_binop_by_ref" is a proxy used by host to call func-references of type (i32, i32)->i32
+ // A module with:
+ // - Imported function "host.call_this" that accepts a callback.
+ // - Exported Wasm function "tell_host_to_call" that calls "host.call_this" with Wasm functions $add and $sub.
+ // - Wasm functions $add and $sub and an imported function $mul used as callbacks
+ // (just to show that imported functions can be referenced too).
+ // - Exported Wasm function "call_binop_by_ref", a proxy used by the host to call func-references of type (i32, i32) -> i32.
const WASM: &str = r#"
(module
(import "host" "call_this" (func $host_callback_caller (param funcref)))
(import "host" "mul" (func $host_mul (param $x i32) (param $y i32) (result i32)))
(func $tell_host_to_call (export "tell_host_to_call")
- (call $host_callback_caller (ref.func $add))
- (call $host_callback_caller (ref.func $sub))
- (call $host_callback_caller (ref.func $host_mul))
+ (call $host_callback_caller (ref.func $add))
+ (call $host_callback_caller (ref.func $sub))
+ (call $host_callback_caller (ref.func $host_mul))
)
(type $binop (func (param i32 i32) (result i32)))
(table 3 funcref)
- (elem (i32.const 0) $add $sub $host_mul) ;; function can only be taken reference of if it's added to a table
+ (elem (i32.const 0) $add $sub $host_mul) ;; Function can only be referenced if added to a table.
(func $add (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
@@ -45,59 +44,63 @@ fn by_func_ref_passed() -> Result<()> {
(table $callback_register 1 funcref)
(func (export "call_binop_by_ref") (param funcref i32 i32) (result i32)
- (table.set $callback_register (i32.const 0) (local.get 0))
+ (table.set $callback_register (i32.const 0) (local.get 0))
(call_indirect $callback_register (type $binop) (local.get 1)(local.get 2)(i32.const 0))
)
)
"#;
- let wasm = wat::parse_str(WASM).expect("failed to parse wat");
+ let wasm = wat::parse_str(WASM).expect("Failed to parse WAT");
let module = Module::parse_bytes(&wasm)?;
let mut store = Store::default();
let mut imports = Imports::new();
- // import host function that takes callbacks and calls them
+
+ // Import host function that takes callbacks and calls them.
imports.define(
"host",
"call_this",
Extern::typed_func(|mut ctx: FuncContext<'_>, fn_ref: FuncRef| -> tinywasm::Result<()> {
let proxy_caller =
ctx.module().exported_func::<(FuncRef, i32, i32), i32>(ctx.store(), "call_binop_by_ref")?;
- // call callback we got as argument using call_binop_by_ref
+ // Call the callback we got as an argument using "call_binop_by_ref".
let res = proxy_caller.call(ctx.store_mut(), (fn_ref, 5, 3))?;
println!("(funcref {fn_ref:?})(5,3) results in {res}");
Ok(())
}),
)?;
- // import host.mul function (one of the functions whose references are taken)
+
+ // Import host.mul function (one of the functions whose references are taken).
imports.define(
"host",
"mul",
Extern::typed_func(|_, args: (i32, i32)| -> tinywasm::Result<i32> { Ok(args.0 * args.1) }),
)?;
+
let instance = module.instantiate(&mut store, Some(imports))?;
- let caller = instance.exported_func::<(), ()>(&mut store, "tell_host_to_call")?;
- // call the tell_host_to_call
+ let caller = instance.exported_func::<(), ()>(&store, "tell_host_to_call")?;
+
+ // Call "tell_host_to_call".
caller.call(&mut store, ())?;
- // interesting detail is that neither $add $sub $mul were exported,
- // but with a little help from proxy "call_binop_by_ref" references to them host was able to call them
+ // An interesting detail is that neither $add, $sub, nor $mul were exported,
+ // but with a little help from the proxy "call_binop_by_ref", references to them are callable by the host.
Ok(())
}
-/// example of returning wasm function as callback to host function
-/// and host function calling it
+/// Example of returning a Wasm function as a callback to a host function
+/// and the host function calling it.
fn by_func_ref_returned() -> Result<()> {
- // a module with:
- // an exported function "what_should_host_call" that returns 3 funcrefs
- // wasm functions $add and $sub and imported function $mul used as callbacks
- // (just to show that imported functions can be referenced too)
- // exported wasm function "call_binop_by_ref" is a proxy used by host to call func-references of type (i32, i32)->i32
+ // A module with:
+ // - An exported function "what_should_host_call" that returns 3 `funcref`s.
+ // - Wasm functions $add and $sub and an imported function $mul used as callbacks
+ // (just to show that imported functions can be referenced too).
+ // - Another exported Wasm function "call_binop_by_ref", a proxy used by the host to call func-references of type (i32, i32) -> i32
const WASM: &str = r#"
(module
(import "host" "mul" (func $host_mul (param $x i32) (param $y i32) (result i32)))
(type $binop (func (param i32 i32) (result i32)))
(table 3 funcref)
- (elem (i32.const 0) $add $sub $host_mul)
+ (elem (i32.const 0) $add $sub $host_mul)
(func $add (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
@@ -109,24 +112,25 @@ fn by_func_ref_returned() -> Result<()> {
i32.sub
)
(func $ref_to_funcs (export "what_should_host_call") (result funcref funcref funcref)
- (ref.func $add)
- (ref.func $sub)
+ (ref.func $add)
+ (ref.func $sub)
(ref.func $host_mul)
)
(table $callback_register 1 funcref)
(func $call (export "call_binop_by_ref") (param funcref i32 i32) (result i32)
- (table.set $callback_register (i32.const 0) (local.get 0))
+ (table.set $callback_register (i32.const 0) (local.get 0))
(call_indirect $callback_register (type $binop) (local.get 1)(local.get 2)(i32.const 0))
)
)
"#;
- let wasm = wat::parse_str(WASM).expect("failed to parse wat");
+ let wasm = wat::parse_str(WASM).expect("Failed to parse WAT");
let module = Module::parse_bytes(&wasm)?;
let mut store = Store::default();
let mut imports = Imports::new();
- // import host.mul function (one of the possible operations)
+
+ // Import host.mul function (one of the possible operations).
imports.define(
"host",
"mul",
@@ -134,19 +138,20 @@ fn by_func_ref_returned() -> Result<()> {
)?;
let instance = module.instantiate(&mut store, Some(imports))?;
- {
- // ask module what should we call
- let funcrefs = {
- let address_getter =
- instance.exported_func::<(), (FuncRef, FuncRef, FuncRef)>(&mut store, "what_should_host_call")?;
- address_getter.call(&mut store, ())?
- };
- let proxy_caller = instance.exported_func::<(FuncRef, i32, i32), i32>(&mut store, "call_binop_by_ref")?;
- for (idx, func_ref) in [funcrefs.0, funcrefs.1, funcrefs.2].iter().enumerate() {
- // call those funcrefs via "call_binop_by_ref"
- let res = proxy_caller.call(&mut store, (*func_ref, 5, 3))?;
- println!("at idx: {idx} funcref {func_ref:?}(5,3) results in {res}");
- }
+
+ // Ask the module what to call.
+ let funcrefs = {
+ let address_getter =
+ instance.exported_func::<(), (FuncRef, FuncRef, FuncRef)>(&store, "what_should_host_call")?;
+ address_getter.call(&mut store, ())?
+ };
+
+ let proxy_caller = instance.exported_func::<(FuncRef, i32, i32), i32>(&store, "call_binop_by_ref")?;
+
+ for (idx, func_ref) in [funcrefs.0, funcrefs.1, funcrefs.2].iter().enumerate() {
+ // Call those `funcref`s via "call_binop_by_ref".
+ let res = proxy_caller.call(&mut store, (*func_ref, 5, 3))?;
+ println!("At idx: {idx}, funcref {func_ref:?}(5,3) results in {res}");
}
Ok(())
}
diff --git a/examples/linking.rs b/examples/linking.rs
index d215898..f94773a 100644
--- a/examples/linking.rs
+++ b/examples/linking.rs
@@ -1,6 +1,7 @@
use eyre::Result;
use tinywasm::{Module, Store};
+// WebAssembly module defining and exporting an `add` function.
const WASM_ADD: &str = r#"
(module
(func $add (param $lhs i32) (param $rhs i32) (result i32)
@@ -10,6 +11,7 @@ const WASM_ADD: &str = r#"
(export "add" (func $add)))
"#;
+// WebAssembly module importing an `add` function and using it.
const WASM_IMPORT: &str = r#"
(module
(import "adder" "add" (func $add (param i32 i32) (result i32)))
@@ -29,13 +31,20 @@ fn main() -> Result<()> {
let import_module = Module::parse_bytes(&wasm_import)?;
let mut store = Store::default();
+
+ // Instantiate the `add` module.
let add_instance = add_module.instantiate(&mut store, None)?;
+ // Link the `adder` namespace to the `add` module's instance.
let mut imports = tinywasm::Imports::new();
imports.link_module("adder", add_instance.id())?;
+
+ // Instantiate the `import` module with the linked imports.
let import_instance = import_module.instantiate(&mut store, Some(imports))?;
+ // Call the `main` function, which uses the imported `add` function.
let main = import_instance.exported_func::<(), i32>(&store, "main")?;
assert_eq!(main.call(&mut store, ())?, 3);
+
Ok(())
}
diff --git a/examples/wasm-rust.rs b/examples/wasm-rust.rs
index 89203c1..429bdcb 100644
--- a/examples/wasm-rust.rs
+++ b/examples/wasm-rust.rs
@@ -14,7 +14,8 @@ use tinywasm::{Extern, FuncContext, Imports, MemoryStringExt, Module, Store};
/// ./examples/rust/build.sh
/// ```
///
-/// This requires the `wasm32-unknown-unknown` target, `binaryen` and `wabt` to be installed.
+/// This requires the `wasm32-unknown-unknown` target, `binaryen`, and `wabt` to be installed:
+///
/// `rustup target add wasm32-unknown-unknown`.
/// <https://github.com/WebAssembly/wabt>
/// <https://github.com/WebAssembly/binaryen>