Tuesday, April 11, 2023

WebAssembly: bidirectional communication between components and host

Still investigating the use of WebAssembly to implement a plugin system using Rust and Wasmer. In the previous post, I could load a WebAssembly plugin that implemented an interface that the host knew about. But since WebAssembly is very limited by design in terms of API, as soon as a plugin wants to interact with the outside world in some shape of form, it needs to be able to call an API the host will provide. Thus the host can ensure safety, performance, etc. without allowing the WebAssembly code direct access to real resources.

So let's say we'd like to customize our greeting message based on the time of day. We're going to need a very simple function to tell us the current hour of the day:

hour: func() -> u32

This goes into host.wai. In our english-rs module we can then import! this file with standard web assembly Rust generation and use it in our implementation of greet:

wai_bindgen_rust::export!("greeter.wai");
wai_bindgen_rust::import!("host.wai");

struct Greeter;

impl crate::greeter::Greeter for Greeter {
/// The language we greet in.
fn language() -> String {
String::from("English")
}

/// Greet the given name.
fn greet(name: String) -> String {
let hour = host::hour();
if hour < 12 {
format!("Good morning, {name}!")
} else if hour < 18 {
format!("Good afternoon, {name}!")
} else {
format!("Good evening, {name}!")
}
}
}

Note how we call the host::hour function and get the hour. Of course here we doing something trivial using standard WebAssembly types like u32, things would become more complicated if the types get more complex.

The host code needs to provide an implementation of the hour function and inject it via imports:

fn hour() -> u32 {
let now = chrono::Local::now();
now.hour()
}
 
fn main() -> Result<()> {
 ...
let imports = imports! {
"host" => {
"hour" => Function::new_typed(&mut store, hour)
},
};
let instance = Instance::new(&mut store, &module, &imports)?;
...

Et voilĂ !

cargo run -- "JP Moresmau"
Language: English
Greeting: Good afternoon, JP Moresmau!

All code can be found as before at https://github.com/JPMoresmau/greet-plugins/tree/wasmer-wai.

Happy WebAssembly and Rust hacking!


No comments: