From 512286c31d4405db5dfa7894ec2cefef7854b738 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 7 Apr 2020 10:45:42 -0700 Subject: [PATCH 1/3] Add Go as an embedding to the book Also take this time to list out all embeddings in the README of wasmtime itself. --- README.md | 24 +++++++++++++ docs/SUMMARY.md | 3 +- docs/examples-c-wasi.md | 2 +- docs/lang-go.md | 76 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 docs/lang-go.md diff --git a/README.md b/README.md index 9ced75f8fbf9..bc051397c18b 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,30 @@ Hello, world! [Cranelift]: https://github.com/bytecodealliance/wasmtime/blob/master/cranelift/README.md [embedded]: https://bytecodealliance.github.io/wasmtime/embed.html +## Language Support + +You can use Wasmtime from a variety of different languages through embeddings of +the implementation: + +* **[Rust]** - the [`wasmtime` crate] +* **[C]** - the [`wasm.h`], [`wasi.h`], and [`wasmtime.h`] headers +* **[Python]** - the [`wasmtime` PyPI package] +* **[.NET]** - the [`Wasmtime` NuGet package] +* **[Go]** - the [wasmtime-go repository] + +[Rust]: https://bytecodealliance.github.io/wasmtime/embed-rust.html +[C]: https://bytecodealliance.github.io/wasmtime/examples-c-embed.html +[`wasmtime` crate]: https://crates.io/crates/wasmtime +[`wasm.h`]: https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h +[`wasi.h`]: https://github.com/bytecodealliance/wasmtime/blob/master/crates/c-api/include/wasi.h +[`wasmtime.h`]: https://github.com/bytecodealliance/wasmtime/blob/master/crates/c-api/include/wasmtime.h +[Python]: https://bytecodealliance.github.io/wasmtime/lang-python.html +[`wasmtime` PyPI package]: https://pypi.org/project/wasmtime/ +[.NET]: https://bytecodealliance.github.io/wasmtime/lang-dotnet.html +[`Wasmtime` NuGet package]: https://www.nuget.org/packages/Wasmtime +[Go]: https://bytecodealliance.github.io/wasmtime/lang-go.html +[wasmtime-go repository]: https://pkg.go.dev/github.com/bytecodealliance/wasmtime-go + ## Documentation [📚 Read the Wasmtime guide here! 📚][guide] diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 8b53a1f29f49..2a47f55f6c08 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -26,9 +26,10 @@ - [Debugging](./examples-c-debugging.md) - [Using multi-value](./examples-c-multi-value.md) - [Using WebAssembly from your lanugage](./lang.md) + - [Rust](./lang-rust.md) - [Python](./lang-python.md) - [.NET](./lang-dotnet.md) - - [Rust](./lang-rust.md) + - [Go](./lang-go.md) - [Bash](./lang-bash.md) - [Using the `wasmtime` CLI](./cli.md) - [Installation](./cli-install.md) diff --git a/docs/examples-c-wasi.md b/docs/examples-c-wasi.md index bcf38345275a..b51dfed6e1a6 100644 --- a/docs/examples-c-wasi.md +++ b/docs/examples-c-wasi.md @@ -10,7 +10,7 @@ This example shows off how to instantiate a wasm module using WASI imports. ## Wasm Source code ```rust,ignore -{{#include ../examples/wasi/wasm/wasi.c}} +{{#include ../examples/wasi/wasm/wasi.rs}} ``` diff --git a/docs/lang-go.md b/docs/lang-go.md new file mode 100644 index 000000000000..b452e5dbd33b --- /dev/null +++ b/docs/lang-go.md @@ -0,0 +1,76 @@ +# Go + +Wasmtime [is available as a Go +Module](https://pkg.go.dev/github.com/bytecodealliance/wasmtime-go). This guide +will go over adding Wasmtime to your project, and some provided examples of what +can be done with WebAssembly modules. + +Make sure you're using Go 1.12 or later with modules support. + +## Getting started and simple example + +First up you'll want to start a new module: + +```sh +$ mkdir hello-wasm +$ cd hello-wasm +$ go mod init hello-wasm +``` + +Next, copy this example WebAssembly text module into your project. It exports a +function for calculating the greatest common denominator of two numbers. + +```wat +{{#include ../examples/gcd.wat}} +``` + +Next, we can write our code in `main.go` which reads this file and runs it: + +```go +package main + +import ( + "fmt" + "github.com/bytecodealliance/wasmtime-go" +) + +func main() { + store := wasmtime.NewStore(wasmtime.NewEngine()) + module, err := wasmtime.NewModuleFromFile(store, "gcd.wat") + check(err) + instance, err := wasmtime.NewInstance(module, []*wasmtime.Extern{}) + check(err) + + gcd := instance.GetExport("gcd").Func() + val, err := gcd.Call(6, 27) + check(err) + fmt.Printf("gcd(6, 27) = %d\n", val.(int32)) +} + +func check(err error) { + if err != nil { + panic(err) + } +} +``` + +And finally we can build and run it: + +```sh +$ go run main.go +gcd(6, 27) = 3 +``` + +If this is the output you see, congrats! You've successfully ran your first +WebAssembly code in Go! + +## More examples and contributing + +The `wasmtime` Go package currently [lives in its own repository outside of +`wasmtime`](https://github.com/bytecodealliance/wasmtime-go) and has a [number +of other more advanced +examples](https://pkg.go.dev/github.com/bytecodealliance/wasmtime-go?tab=doc#pkg-examples) +as well. Feel free to browse those, but if you find anything missing don't +hesitate to [open an +issue](https://github.com/bytecodealliance/wasmtime-go/issues/new) and let us +know if you have any questions! From d6113b2f6b18f7a9ad01f95e198155b03bdc466f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 7 Apr 2020 14:40:16 -0700 Subject: [PATCH 2/3] Touch up docs --- docs/SUMMARY.md | 4 +- docs/embed-c.md | 4 -- docs/embed-rust.md | 171 --------------------------------------------- docs/embed.md | 10 --- docs/lang-c.md | 3 + docs/lang-go.md | 4 +- docs/lang-rust.md | 170 +++++++++++++++++++++++++++++++++++++++++++- docs/lang.md | 11 ++- 8 files changed, 185 insertions(+), 192 deletions(-) delete mode 100644 docs/embed-c.md delete mode 100644 docs/embed-rust.md delete mode 100644 docs/embed.md create mode 100644 docs/lang-c.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 2a47f55f6c08..f2cfcf34a837 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -27,6 +27,7 @@ - [Using multi-value](./examples-c-multi-value.md) - [Using WebAssembly from your lanugage](./lang.md) - [Rust](./lang-rust.md) + - [C](./lang-c.md) - [Python](./lang-python.md) - [.NET](./lang-dotnet.md) - [Go](./lang-go.md) @@ -40,9 +41,6 @@ - [C/C++](./wasm-c.md) - [WebAssembly Text Format (`*.wat`)](./wasm-wat.md) - [Example: Markdown Parser](./wasm-markdown.md) -- [Embedding Wasmtime](embed.md) - - [Rust API](./embed-rust.md) - - [C/C++ API](./embed-c.md) - [Stability](stability.md) - [Release Process](./stability-release.md) - [Platform Support](./stability-platform-support.md) diff --git a/docs/embed-c.md b/docs/embed-c.md deleted file mode 100644 index 20c5d65b517d..000000000000 --- a/docs/embed-c.md +++ /dev/null @@ -1,4 +0,0 @@ -# Embedding Wasmtime in C - -... more coming soon - diff --git a/docs/embed-rust.md b/docs/embed-rust.md deleted file mode 100644 index e3c4b7501bf9..000000000000 --- a/docs/embed-rust.md +++ /dev/null @@ -1,171 +0,0 @@ -# Embedding Wasmtime in Rust - -This document shows an example of how to embed Wasmtime using the [Rust -API][apidoc] to execute a simple wasm program. Be sure to also check out the -[full API documentation][apidoc] for a full listing of what the [`wasmtime` -crate][wasmtime] has to offer and the [book examples for -Rust](./examples-rust-embed.md) for more information. - -[apidoc]: https://bytecodealliance.github.io/wasmtime/api/wasmtime/ -[crate]: https://crates.io/crates/wasmtime - -## Creating the WebAssembly to execute - -Creation of a WebAssembly file is generally covered by the [Writing -WebAssembly chapter](./wasm.md), so we'll just assume that you've already got a -wasm file on hand for the rest of this tutorial. To make things simple we'll -also just assume you've got a `hello.wat` file which looks like this: - -```wat -(module - (func (export "answer") (result i32) - i32.const 42 - ) -) -``` - -Here we're just exporting one function which returns an integer that we'll read -from Rust. - -## Hello, World! - -First up let's create a rust project - -```sh -$ cargo new --bin wasmtime_hello -$ cd wasmtime_hello -``` - -Next you'll want to add `hello.wat` to the root of your project. - -We will be using the `wasmtime` crate to run the wasm file, so next up we need a -dependency in `Cargo.toml`: - -```toml -[dependencies] -wasmtime = "0.12.0" -``` - -Next up let's write the code that we need to execute this wasm file. The -simplest version of this looks like so: - -```rust,no_run -# extern crate wasmtime; -use std::error::Error; -use wasmtime::*; - -fn main() -> Result<(), Box> { - // A `Store` is a sort of "global object" in a sense, but for now it suffices - // to say that it's generally passed to most constructors. - let store = Store::default(); - -# if false { - // We start off by creating a `Module` which represents a compiled form - // of our input wasm module. In this case it'll be JIT-compiled after - // we parse the text format. - let module = Module::from_file(&store, "hello.wat")?; -# } -# let module = Module::new(&store, r#"(module (func (export "answer") (result i32) i32.const 42))"#)?; - - // After we have a compiled `Module` we can then instantiate it, creating - // an `Instance` which we can actually poke at functions on. - let instance = Instance::new(&module, &[])?; - - // The `Instance` gives us access to various exported functions and items, - // which we access here to pull out our `answer` exported function and - // run it. - let answer = instance.get_export("answer") - .expect("export named `answer` not found") - .func() - .expect("export `answer` was not a function"); - - // There's a few ways we can call the `answer` `Func` value. The easiest - // is to statically assert its signature with `get0` (in this case asserting - // it takes no arguments and returns one i32) and then call it. - let answer = answer.get0::()?; - - // And finally we can call our function! Note that the error propagation - // with `?` is done to handle the case where the wasm function traps. - let result = answer()?; - println!("Answer: {:?}", result); - Ok(()) -} -``` - -We can build and execute our example with `cargo run`. Note that by depending on -`wasmtime` you're depending on a JIT compiler, so it may take a moment to build -all of its dependencies: - -```sh -$ cargo run - Compiling ... - ... - Finished dev [unoptimized + debuginfo] target(s) in 42.32s - Running `wasmtime_hello/target/debug/wasmtime_hello` -Answer: 42 -``` - -and there we go! We've now executed our first WebAssembly in `wasmtime` and -gotten the result back. - -## Importing Host Functionality - -What we've just seen is a pretty small example of how to call a wasm function -and take a look at the result. Most interesting wasm modules, however, are going -to import some functions to do something a bit more interesting. For that you'll -need to provide imported functions from Rust for wasm to call! - -Let's take a look at a wasm module which imports a logging function as well as -some simple arithmetic from the environment. - -```wat -(module - (import "" "log" (func $log (param i32))) - (import "" "double" (func $double (param i32) (result i32))) - (func (export "run") (result i32) - i32.const 0 - call $log - i32.const 1 - call $log - i32.const 2 - call $double - call $log - ) -) -``` - -This wasm module will call our `"log"` import a few times and then also call the -`"double"` import. We can compile and instantiate this module with code that -looks like this: - -```rust,no_run -# extern crate wasmtime; -# use std::error::Error; -# use wasmtime::*; -# fn main() -> Result<(), Box> { -# let store = Store::default(); -# let module = Module::new(&store, r#" -# (module -# (import "" "log" (func $log (param i32))) -# (import "" "double" (func $double (param i32) (result i32))))"#)?; -// First we can create our `log` function, which will simply print out the -// parameter it receives. -let log = Func::wrap(&store, |param: i32| { - println!("log: {}", param); -}); - -// Next we can create our double function which doubles the input it receives. -let double = Func::wrap(&store, |param: i32| param * 2); - -// When instantiating the module we now need to provide the imports to the -// instantiation process. This is the second slice argument, where each -// entry in the slice must line up with the imports in the module. -let instance = Instance::new(&module, &[log.into(), double.into()])?; -# Ok(()) -# } -``` - -Note that there's a number of ways to define a `Func`, be sure to [consult its -documentation][`Func`] for other ways to create a host-defined function. - -[`Func`]: https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Func.html diff --git a/docs/embed.md b/docs/embed.md deleted file mode 100644 index ceddd05db217..000000000000 --- a/docs/embed.md +++ /dev/null @@ -1,10 +0,0 @@ -# Embedding Wasmtime - -Wasmtime can be used as a library to embed WebAssembly execution support -within applications. It has a Rust API, and also supports the official -[WebAssembly C API]. - -* [Rust](embed-rust.md) -* [C](embed-c.md) - -[WebAssembly C API]: https://github.com/WebAssembly/wasm-c-api diff --git a/docs/lang-c.md b/docs/lang-c.md new file mode 100644 index 000000000000..fa1244d2def1 --- /dev/null +++ b/docs/lang-c.md @@ -0,0 +1,3 @@ +# C + +... more coming soon diff --git a/docs/lang-go.md b/docs/lang-go.md index b452e5dbd33b..14020d981b7c 100644 --- a/docs/lang-go.md +++ b/docs/lang-go.md @@ -66,8 +66,8 @@ WebAssembly code in Go! ## More examples and contributing -The `wasmtime` Go package currently [lives in its own repository outside of -`wasmtime`](https://github.com/bytecodealliance/wasmtime-go) and has a [number +The `wasmtime` Go package [lives in its own +repository](https://github.com/bytecodealliance/wasmtime-go) and has a [number of other more advanced examples](https://pkg.go.dev/github.com/bytecodealliance/wasmtime-go?tab=doc#pkg-examples) as well. Feel free to browse those, but if you find anything missing don't diff --git a/docs/lang-rust.md b/docs/lang-rust.md index 2bdd548ccf4c..c87d1bffcea5 100644 --- a/docs/lang-rust.md +++ b/docs/lang-rust.md @@ -1,3 +1,171 @@ # Using WebAssembly from Rust -... more coming soon +This document shows an example of how to embed Wasmtime using the [Rust +API][apidoc] to execute a simple wasm program. Be sure to also check out the +[full API documentation][apidoc] for a full listing of what the [`wasmtime` +crate][wasmtime] has to offer and the [book examples for +Rust](./examples-rust-embed.md) for more information. + +[apidoc]: https://bytecodealliance.github.io/wasmtime/api/wasmtime/ +[wasmtime]: https://crates.io/crates/wasmtime + +## Creating the WebAssembly to execute + +Creation of a WebAssembly file is generally covered by the [Writing +WebAssembly chapter](./wasm.md), so we'll just assume that you've already got a +wasm file on hand for the rest of this tutorial. To make things simple we'll +also just assume you've got a `hello.wat` file which looks like this: + +```wat +(module + (func (export "answer") (result i32) + i32.const 42 + ) +) +``` + +Here we're just exporting one function which returns an integer that we'll read +from Rust. + +## Hello, World! + +First up let's create a rust project + +```sh +$ cargo new --bin wasmtime_hello +$ cd wasmtime_hello +``` + +Next you'll want to add `hello.wat` to the root of your project. + +We will be using the `wasmtime` crate to run the wasm file, so next up we need a +dependency in `Cargo.toml`: + +```toml +[dependencies] +wasmtime = "0.12.0" +``` + +Next up let's write the code that we need to execute this wasm file. The +simplest version of this looks like so: + +```rust,no_run +# extern crate wasmtime; +use std::error::Error; +use wasmtime::*; + +fn main() -> Result<(), Box> { + // A `Store` is a sort of "global object" in a sense, but for now it suffices + // to say that it's generally passed to most constructors. + let store = Store::default(); + +# if false { + // We start off by creating a `Module` which represents a compiled form + // of our input wasm module. In this case it'll be JIT-compiled after + // we parse the text format. + let module = Module::from_file(&store, "hello.wat")?; +# } +# let module = Module::new(&store, r#"(module (func (export "answer") (result i32) i32.const 42))"#)?; + + // After we have a compiled `Module` we can then instantiate it, creating + // an `Instance` which we can actually poke at functions on. + let instance = Instance::new(&module, &[])?; + + // The `Instance` gives us access to various exported functions and items, + // which we access here to pull out our `answer` exported function and + // run it. + let answer = instance.get_export("answer") + .expect("export named `answer` not found") + .func() + .expect("export `answer` was not a function"); + + // There's a few ways we can call the `answer` `Func` value. The easiest + // is to statically assert its signature with `get0` (in this case asserting + // it takes no arguments and returns one i32) and then call it. + let answer = answer.get0::()?; + + // And finally we can call our function! Note that the error propagation + // with `?` is done to handle the case where the wasm function traps. + let result = answer()?; + println!("Answer: {:?}", result); + Ok(()) +} +``` + +We can build and execute our example with `cargo run`. Note that by depending on +`wasmtime` you're depending on a JIT compiler, so it may take a moment to build +all of its dependencies: + +```sh +$ cargo run + Compiling ... + ... + Finished dev [unoptimized + debuginfo] target(s) in 42.32s + Running `wasmtime_hello/target/debug/wasmtime_hello` +Answer: 42 +``` + +and there we go! We've now executed our first WebAssembly in `wasmtime` and +gotten the result back. + +## Importing Host Functionality + +What we've just seen is a pretty small example of how to call a wasm function +and take a look at the result. Most interesting wasm modules, however, are going +to import some functions to do something a bit more interesting. For that you'll +need to provide imported functions from Rust for wasm to call! + +Let's take a look at a wasm module which imports a logging function as well as +some simple arithmetic from the environment. + +```wat +(module + (import "" "log" (func $log (param i32))) + (import "" "double" (func $double (param i32) (result i32))) + (func (export "run") (result i32) + i32.const 0 + call $log + i32.const 1 + call $log + i32.const 2 + call $double + call $log + ) +) +``` + +This wasm module will call our `"log"` import a few times and then also call the +`"double"` import. We can compile and instantiate this module with code that +looks like this: + +```rust,no_run +# extern crate wasmtime; +# use std::error::Error; +# use wasmtime::*; +# fn main() -> Result<(), Box> { +# let store = Store::default(); +# let module = Module::new(&store, r#" +# (module +# (import "" "log" (func $log (param i32))) +# (import "" "double" (func $double (param i32) (result i32))))"#)?; +// First we can create our `log` function, which will simply print out the +// parameter it receives. +let log = Func::wrap(&store, |param: i32| { + println!("log: {}", param); +}); + +// Next we can create our double function which doubles the input it receives. +let double = Func::wrap(&store, |param: i32| param * 2); + +// When instantiating the module we now need to provide the imports to the +// instantiation process. This is the second slice argument, where each +// entry in the slice must line up with the imports in the module. +let instance = Instance::new(&module, &[log.into(), double.into()])?; +# Ok(()) +# } +``` + +Note that there's a number of ways to define a `Func`, be sure to [consult its +documentation][`Func`] for other ways to create a host-defined function. + +[`Func`]: https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Func.html diff --git a/docs/lang.md b/docs/lang.md index ab5adf5f48bb..2c1b0c6a89e2 100644 --- a/docs/lang.md +++ b/docs/lang.md @@ -1,3 +1,12 @@ # Using WebAssembly from your Language -... more coming soon +Wasmtime can be used as a library to embed WebAssembly execution support +within applications. Wasmtime is written in Rust, but bindings are available +through a C API for a number of other languages too: + +* [Rust](lang-rust.md) +* [C](lang-c.md) +* [Python](lang-python.md) +* [.NET](lang-dotnet.md) +* [Go](lang-go.md) +* [Bash](lang-bash.md) From 99d4e88f29b2af3d4e55e83b9fac4939d4ad805f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 8 Apr 2020 09:03:13 -0700 Subject: [PATCH 3/3] Update Rust link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc051397c18b..3356f583bde3 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ the implementation: * **[.NET]** - the [`Wasmtime` NuGet package] * **[Go]** - the [wasmtime-go repository] -[Rust]: https://bytecodealliance.github.io/wasmtime/embed-rust.html +[Rust]: https://bytecodealliance.github.io/wasmtime/lang-rust.html [C]: https://bytecodealliance.github.io/wasmtime/examples-c-embed.html [`wasmtime` crate]: https://crates.io/crates/wasmtime [`wasm.h`]: https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h