An example of running wasmtime as a host, with callbacks.
This commit is contained in:
commit
d0489776ee
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
**/target
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "rust-wasi-markdown"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.70"
|
||||
pulldown-cmark = "0.9.2"
|
||||
structopt = "0.3.26"
|
||||
wasmtime = "7.0.0"
|
|
@ -0,0 +1,11 @@
|
|||
# Hello, World!
|
||||
|
||||
This is my first WASI program. Kinda sucks, huh?
|
||||
|
||||
> Don't say that!
|
||||
|
||||
But why not?
|
||||
|
||||
> Because this is cool.
|
||||
|
||||
Who says?
|
|
@ -0,0 +1,5 @@
|
|||
(module
|
||||
(func $hello (import "" "hello"))
|
||||
(func (export "run") (call $hello)))
|
||||
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
use anyhow::Result;
|
||||
use wasmtime::*;
|
||||
|
||||
struct MyState {
|
||||
name: String,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
const HELLO: &[u8; 78] =
|
||||
b"(module (func $hello (import \"\" \"hello\")) (func (export \"run\") (call $hello)))";
|
||||
|
||||
fn main() -> Result<()> {
|
||||
println!("Compiling module...");
|
||||
|
||||
// The Engine is the thing that manages and runs WASM instances.
|
||||
let engine = Engine::default();
|
||||
|
||||
// The Module loads, compiles, and creates a new WASM module, ready to be
|
||||
// run.
|
||||
let module = Module::new(&engine, HELLO)?;
|
||||
|
||||
println!("Initializing...");
|
||||
// The Store is where a WASM instance runs and includes its memory pages. It
|
||||
// is the mechanism through which the host and guest programs interact.
|
||||
let mut store = Store::new(
|
||||
&engine,
|
||||
MyState {
|
||||
name: "hello world".to_string(),
|
||||
count: 0,
|
||||
},
|
||||
);
|
||||
|
||||
println!("Creating callback...");
|
||||
// A Func is a function defined by the host program and that can be called
|
||||
// from a WASM module. Here, we're creating a host function that accesses
|
||||
// data inside the store, and increments a mutable value within that data.
|
||||
// Due to the nature of the store, all such functions end up as Fn: Send +
|
||||
// Sync + 'static, with no 'FnMut' or 'FnOnce' defined, but the `Caller`
|
||||
// type there still grants access to the inner workings. See the
|
||||
// documentation for more.
|
||||
let hello_func = Func::wrap(&mut store, |mut caller: Caller<'_, MyState>| {
|
||||
println!("Calling back...");
|
||||
println!("> {}, {}", caller.data().name, caller.data().count);
|
||||
caller.data_mut().count += 1;
|
||||
});
|
||||
|
||||
// An Instance is a running instance of the WASM module. By "running" I mean
|
||||
// that it is now somewhere in memory and its functions can be called by the
|
||||
// host. Note that the imports put *into* the instance are in order, not
|
||||
// named, and must be extracted by a similarly ordered collection of imports
|
||||
// on the other end.
|
||||
println!("Instantiating module...");
|
||||
let imports = [hello_func.into()];
|
||||
let instance = Instance::new(&mut store, &module, &imports)?;
|
||||
|
||||
// Inside the module, we have a named export, "run". Here, we access it.
|
||||
println!("Extracting import...");
|
||||
let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
|
||||
|
||||
// And now we run it a couple of times. `run` calls `hello_func` defined
|
||||
// above, and with each run the data persistent in the `store` object gets
|
||||
// updated, so we can see the count rising:
|
||||
println!("Running export...");
|
||||
run.call(&mut store, ())?;
|
||||
run.call(&mut store, ())?;
|
||||
run.call(&mut store, ())?;
|
||||
run.call(&mut store, ())?;
|
||||
run.call(&mut store, ())?;
|
||||
|
||||
println!("Done!");
|
||||
|
||||
/*
|
||||
The output should look like this:
|
||||
|
||||
Compiling module...
|
||||
Initializing...
|
||||
Creating callback...
|
||||
Instantiating module...
|
||||
Extracting import...
|
||||
Running export...
|
||||
Calling back...
|
||||
> hello world, 0
|
||||
Calling back...
|
||||
> hello world, 1
|
||||
Calling back...
|
||||
> hello world, 2
|
||||
Calling back...
|
||||
> hello world, 3
|
||||
Calling back...
|
||||
> hello world, 4
|
||||
Done!
|
||||
*/
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue