wasmer/examples/plugin.rs

147 lines
4.7 KiB
Rust
Raw Normal View History

2019-04-27 01:45:18 +00:00
use wasmer_runtime::{func, imports, instantiate};
use wasmer_runtime_core::vm::Ctx;
use wasmer_wasi::{
generate_import_object,
state::{self, WasiFile},
types,
};
2019-04-27 01:45:18 +00:00
2019-04-29 18:27:19 +00:00
static PLUGIN_LOCATION: &'static str = "examples/plugin-for-example.wasm";
2019-04-27 01:45:18 +00:00
fn it_works(_ctx: &mut Ctx) -> i32 {
println!("Hello from outside WASI");
5
}
#[derive(Debug)]
pub struct LoggingWrapper {
pub wasm_module_name: String,
}
// std io trait boiler plate so we can implement WasiFile
// LoggingWrapper is a write-only type so we just want to immediately
// fail when reading or Seeking
impl std::io::Read for LoggingWrapper {
fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"can not read from logging wrapper",
))
}
fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> std::io::Result<usize> {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"can not read from logging wrapper",
))
}
fn read_to_string(&mut self, _buf: &mut String) -> std::io::Result<usize> {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"can not read from logging wrapper",
))
}
fn read_exact(&mut self, _buf: &mut [u8]) -> std::io::Result<()> {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"can not read from logging wrapper",
))
}
}
impl std::io::Seek for LoggingWrapper {
fn seek(&mut self, _pos: std::io::SeekFrom) -> std::io::Result<u64> {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"can not seek logging wrapper",
))
}
}
impl std::io::Write for LoggingWrapper {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let stdout = std::io::stdout();
let mut out = stdout.lock();
out.write(b"[")?;
out.write(self.wasm_module_name.as_bytes())?;
out.write(b"]: ")?;
out.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
std::io::stdout().flush()
}
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
let stdout = std::io::stdout();
let mut out = stdout.lock();
out.write(b"[")?;
out.write(self.wasm_module_name.as_bytes())?;
out.write(b"]: ")?;
out.write_all(buf)
}
fn write_fmt(&mut self, fmt: std::fmt::Arguments) -> std::io::Result<()> {
let stdout = std::io::stdout();
let mut out = stdout.lock();
out.write(b"[")?;
out.write(self.wasm_module_name.as_bytes())?;
out.write(b"]: ")?;
out.write_fmt(fmt)
}
}
// the WasiFile methods aren't relevant for a write-only Stdout-like implementation
impl WasiFile for LoggingWrapper {
fn last_accessed(&self) -> u64 {
0
}
fn last_modified(&self) -> u64 {
0
}
fn created_time(&self) -> u64 {
0
}
fn size(&self) -> u64 {
0
}
}
/// Called by the program when it wants to set itself up
fn initialize(ctx: &mut Ctx) {
let state = state::get_wasi_state(ctx);
let wasi_file_inner = LoggingWrapper {
wasm_module_name: "example module name".to_string(),
};
// swap stdout with our new wasifile
let _old_stdout = state
.fs
.swap_file(types::__WASI_STDOUT_FILENO, Box::new(wasi_file_inner))
.unwrap();
}
2019-04-27 01:45:18 +00:00
fn main() {
2019-04-29 18:33:03 +00:00
// Load the plugin data
2019-04-29 18:27:19 +00:00
let wasm_bytes = std::fs::read(PLUGIN_LOCATION).expect(&format!(
"Could not read in WASM plugin at {}",
PLUGIN_LOCATION
));
2019-04-27 01:45:18 +00:00
// WASI imports
let mut base_imports = generate_import_object(vec![], vec![], vec![], vec![]);
2019-04-27 01:45:18 +00:00
// env is the default namespace for extern functions
let custom_imports = imports! {
"env" => {
"it_works" => func!(it_works),
"initialize" => func!(initialize),
2019-04-27 01:45:18 +00:00
},
};
// The WASI imports object contains all required import functions for a WASI module to run.
// Extend this imports with our custom imports containing "it_works" function so that our custom wasm code may run.
2019-04-27 01:45:18 +00:00
base_imports.extend(custom_imports);
let instance =
2019-04-29 18:27:19 +00:00
instantiate(&wasm_bytes[..], &base_imports).expect("failed to instantiate wasm module");
2019-04-27 01:45:18 +00:00
let main = instance.func::<(), ()>("_start").unwrap();
main.call().expect("Could not initialize");
// get a reference to the function "plugin_entrypoint" which takes an i32 and returns an i32
2019-04-27 01:45:18 +00:00
let entry_point = instance.func::<(i32), i32>("plugin_entrypoint").unwrap();
// call the "entry_point" function in WebAssembly with the number "2" as the i32 argument
2019-04-27 01:45:18 +00:00
let result = entry_point.call(2).expect("failed to execute plugin");
println!("result: {}", result);
}