Add Go as an embedding to the book (#1481)

* Add Go as an embedding to the book

Also take this time to list out all embeddings in the README of wasmtime
itself.
This commit is contained in:
Alex Crichton
2020-04-08 11:03:30 -05:00
committed by GitHub
parent 328de8bf9b
commit 44e897ddad
10 changed files with 286 additions and 192 deletions

View File

@@ -86,6 +86,30 @@ Hello, world!
[Cranelift]: https://github.com/bytecodealliance/wasmtime/blob/master/cranelift/README.md [Cranelift]: https://github.com/bytecodealliance/wasmtime/blob/master/cranelift/README.md
[embedded]: https://bytecodealliance.github.io/wasmtime/embed.html [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/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
[`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 ## Documentation
[📚 Read the Wasmtime guide here! 📚][guide] [📚 Read the Wasmtime guide here! 📚][guide]

View File

@@ -26,9 +26,11 @@
- [Debugging](./examples-c-debugging.md) - [Debugging](./examples-c-debugging.md)
- [Using multi-value](./examples-c-multi-value.md) - [Using multi-value](./examples-c-multi-value.md)
- [Using WebAssembly from your lanugage](./lang.md) - [Using WebAssembly from your lanugage](./lang.md)
- [Rust](./lang-rust.md)
- [C](./lang-c.md)
- [Python](./lang-python.md) - [Python](./lang-python.md)
- [.NET](./lang-dotnet.md) - [.NET](./lang-dotnet.md)
- [Rust](./lang-rust.md) - [Go](./lang-go.md)
- [Bash](./lang-bash.md) - [Bash](./lang-bash.md)
- [Using the `wasmtime` CLI](./cli.md) - [Using the `wasmtime` CLI](./cli.md)
- [Installation](./cli-install.md) - [Installation](./cli-install.md)
@@ -39,9 +41,6 @@
- [C/C++](./wasm-c.md) - [C/C++](./wasm-c.md)
- [WebAssembly Text Format (`*.wat`)](./wasm-wat.md) - [WebAssembly Text Format (`*.wat`)](./wasm-wat.md)
- [Example: Markdown Parser](./wasm-markdown.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) - [Stability](stability.md)
- [Release Process](./stability-release.md) - [Release Process](./stability-release.md)
- [Platform Support](./stability-platform-support.md) - [Platform Support](./stability-platform-support.md)

View File

@@ -1,4 +0,0 @@
# Embedding Wasmtime in C
... more coming soon

View File

@@ -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<dyn Error>> {
// 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::<i32>()?;
// 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<dyn Error>> {
# 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

View File

@@ -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

View File

@@ -10,7 +10,7 @@ This example shows off how to instantiate a wasm module using WASI imports.
## Wasm Source code ## Wasm Source code
```rust,ignore ```rust,ignore
{{#include ../examples/wasi/wasm/wasi.c}} {{#include ../examples/wasi/wasm/wasi.rs}}
``` ```

3
docs/lang-c.md Normal file
View File

@@ -0,0 +1,3 @@
# C
... more coming soon

76
docs/lang-go.md Normal file
View File

@@ -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 [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
hesitate to [open an
issue](https://github.com/bytecodealliance/wasmtime-go/issues/new) and let us
know if you have any questions!

View File

@@ -1,3 +1,171 @@
# Using WebAssembly from Rust # 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<dyn Error>> {
// 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::<i32>()?;
// 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<dyn Error>> {
# 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

View File

@@ -1,3 +1,12 @@
# Using WebAssembly from your Language # 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)