Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extending WASI plugin example #399

Merged
merged 14 commits into from
Apr 29, 2019
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
wasmer-wasi = { path = "lib/wasi", optional = true }

[workspace]
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi"]
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi", "examples/plugin-for-example"]

[build-dependencies]
wabt = "0.7.2"
Expand All @@ -49,3 +49,7 @@ fast-tests = []
"backend:singlepass" = ["wasmer-singlepass-backend"]
wasi = ["wasmer-wasi"]
vfs = ["wasmer-runtime-abi"]

[[example]]
name = "plugin"
crate-type = ["bin"]
Binary file added examples/plugin-for-example.wasm
Binary file not shown.
7 changes: 7 additions & 0 deletions examples/plugin-for-example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved
name = "plugin-for-example"
version = "0.1.0"
authors = ["The Wasmer Engineering Team <[email protected]>"]
edition = "2018"

[dependencies]
33 changes: 33 additions & 0 deletions examples/plugin-for-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# WASI plugin example

In this example we extend the imports of Wasmer's WASI ABI to demonstrate how custom plugins work.

See the `wasmer/examples/plugin.rs` file for the source code of the host system.

## Compiling

xmclark marked this conversation as resolved.
Show resolved Hide resolved
```
# Install an up to date version of Rust nightly
# Add the target
rustup target add wasm32-unknown-wasi
# build it
cargo build --release --target=wasm32-unknown-wasi
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved
# copy it to examples folder
cp ../../target/wasm32-unknown-wasi/release/plugin-for-example.wasm ../
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may also be worth noting that WASI is only supported on windows with the gnu toolchain. If you can't find a way to work this detail into the example, that's ok, but it could be another stumbling block for some.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I'm not sure exactly what to add to say that. What I mean is, does that show up in the target dir?

```

## Running
```
# Go back to top level Wasmer dir
cd ..
# Run the example
cargo run --example plugin
```

## Explanation

In this example, we instantiate a system with an extended (WASI)[wasi] ABI, allowing our program to rely on Wasmer's implementation of the syscalls defined by WASI as well as our own that we made. This allows us to use the full power of an existing ABI, like WASI, and give it super-powers for our specific use case.

Because the Rust WASI doesn't support the crate type of `cdylib`, we have to include a main function which we don't use.
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved

[wasi]: https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/
12 changes: 12 additions & 0 deletions examples/plugin-for-example/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
extern "C" {
fn it_works() -> i32;
}

#[no_mangle]
pub fn plugin_entrypoint(n: i32) -> i32 {
println!("Hello from inside WASI");
let result = unsafe { it_works() };
result + n
}

pub fn main() {}
28 changes: 28 additions & 0 deletions examples/plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use wasmer_runtime::{func, imports, instantiate};
use wasmer_runtime_core::vm::Ctx;
use wasmer_wasi::generate_import_object;

static PLUGIN_WASM: &'static [u8] = include_bytes!("plugin-for-example.wasm");
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved

fn it_works(_ctx: &mut Ctx) -> i32 {
println!("Hello from outside WASI");
5
}

fn main() {
// WASI imports
let mut base_imports = generate_import_object(vec![], vec![], vec![]);
// env is the default namespace for extern functions
let custom_imports = imports! {
"env" => {
"it_works" => func!(it_works),
},
};
base_imports.extend(custom_imports);
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved
let instance =
instantiate(PLUGIN_WASM, &base_imports).expect("failed to instantiate wasm module");

let entry_point = instance.func::<(i32), i32>("plugin_entrypoint").unwrap();
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved
let result = entry_point.call(2).expect("failed to execute plugin");
MarkMcCaskey marked this conversation as resolved.
Show resolved Hide resolved
println!("result: {}", result);
}