|
|
@ -18,7 +18,7 @@ Let's create a simple WebAssembly file with a single exported function that retu |
|
|
|
|
|
|
|
# Create rust project |
|
|
|
|
|
|
|
``` |
|
|
|
```sh |
|
|
|
$ cargo new --bin wasmtime_hello |
|
|
|
$ cd wasmtime_hello |
|
|
|
$ cp $WASM_FILES/hello.wasm . |
|
|
@ -26,7 +26,7 @@ $ cp $WASM_FILES/hello.wasm . |
|
|
|
|
|
|
|
We will be using the wasmtime engine/API to run the wasm file, so we will add the dependency to `Cargo.toml`: |
|
|
|
|
|
|
|
``` |
|
|
|
```toml |
|
|
|
[dependencies] |
|
|
|
wasmtime = "<current version>" |
|
|
|
``` |
|
|
@ -36,6 +36,7 @@ where "<current version>" is the current version number of the `wasmtime` crate. |
|
|
|
It is time to add code to the `src/main.rs`. First, storage needs to be activated: |
|
|
|
|
|
|
|
```rust |
|
|
|
# extern crate wasmtime; |
|
|
|
use wasmtime::*; |
|
|
|
|
|
|
|
let store = Store::default(); |
|
|
@ -43,18 +44,32 @@ let store = Store::default(); |
|
|
|
|
|
|
|
The `hello.wasm` can be read from the file system and provided to the `Module` object constructor as `&[u8]`: |
|
|
|
|
|
|
|
```rust |
|
|
|
```rust,no_run |
|
|
|
# extern crate wasmtime; |
|
|
|
# use wasmtime::*; |
|
|
|
# fn main() -> Result<(), Box<dyn std::error::Error>> { |
|
|
|
# let store = Store::default(); |
|
|
|
use std::fs::read; |
|
|
|
|
|
|
|
let hello_wasm = read("hello.wasm").expect("wasm file"); |
|
|
|
let hello_wasm = read("hello.wasm")?; |
|
|
|
|
|
|
|
let module = Module::new(&store, &hello_wasm).expect("wasm module"); |
|
|
|
let module = Module::new(&store, &hello_wasm)?; |
|
|
|
# Ok(()) |
|
|
|
# } |
|
|
|
``` |
|
|
|
|
|
|
|
The module instance can now be created. Normally, you would provide exports, but in this case, there are none required: |
|
|
|
The module instance can now be created. Normally, you would provide imports, but |
|
|
|
in this case, there are none required: |
|
|
|
|
|
|
|
```rust |
|
|
|
let instance = Instance::new(&module, &[]).expect("wasm instance"); |
|
|
|
# extern crate wasmtime; |
|
|
|
# use wasmtime::*; |
|
|
|
# fn main() -> Result<(), Box<dyn std::error::Error>> { |
|
|
|
# let store = Store::default(); |
|
|
|
# let module = Module::new(&store, "(module)")?; |
|
|
|
let instance = Instance::new(&module, &[])?; |
|
|
|
# Ok(()) |
|
|
|
# } |
|
|
|
``` |
|
|
|
|
|
|
|
Everything is set. If a WebAssembly module has a start function -- it was run. |
|
|
@ -62,34 +77,74 @@ The instance's exports can be used at this point. wasmtime provides functions |
|
|
|
to get an export by name, and ensure that it's a function: |
|
|
|
|
|
|
|
```rust |
|
|
|
# extern crate wasmtime; |
|
|
|
# use wasmtime::*; |
|
|
|
# fn main() -> Result<(), Box<dyn std::error::Error>> { |
|
|
|
# let store = Store::default(); |
|
|
|
# let module = Module::new(&store, r#"(module (func (export "answer")))"#)?; |
|
|
|
# let instance = Instance::new(&module, &[])?; |
|
|
|
let answer = instance.get_export("answer").expect("answer").func().expect("function"); |
|
|
|
# Ok(()) |
|
|
|
# } |
|
|
|
``` |
|
|
|
|
|
|
|
The exported function can be called using the `call` method. The exported "answer" function accepts no parameters and returns a single `i32` value. |
|
|
|
The exported function can be called using the `call` method. The exported |
|
|
|
"answer" function accepts no parameters and returns a single `i32` value. |
|
|
|
|
|
|
|
```rust |
|
|
|
let result = answer.call(&[]).expect("success"); |
|
|
|
# extern crate wasmtime; |
|
|
|
# use wasmtime::*; |
|
|
|
# fn main() -> Result<(), Box<dyn std::error::Error>> { |
|
|
|
# let store = Store::default(); |
|
|
|
# let module = Module::new(&store, r#"(module (func (export "answer") (result i32) i32.const 2))"#)?; |
|
|
|
# let instance = Instance::new(&module, &[])?; |
|
|
|
# let answer = instance.get_export("answer").expect("answer").func().expect("function"); |
|
|
|
let result = answer.call(&[])?; |
|
|
|
println!("Answer: {:?}", result[0].i32()); |
|
|
|
# Ok(()) |
|
|
|
# } |
|
|
|
``` |
|
|
|
|
|
|
|
Since we know the signature of the function ahead of time, we can also assert |
|
|
|
its signature and call the function directly without doing conversions: |
|
|
|
|
|
|
|
```rust |
|
|
|
# extern crate wasmtime; |
|
|
|
# use wasmtime::*; |
|
|
|
# fn main() -> Result<(), Box<dyn std::error::Error>> { |
|
|
|
# let store = Store::default(); |
|
|
|
# let module = Module::new(&store, r#"(module (func (export "answer") (result i32) i32.const 2))"#)?; |
|
|
|
# let instance = Instance::new(&module, &[])?; |
|
|
|
# let answer = instance.get_export("answer").expect("answer").func().expect("function"); |
|
|
|
let answer = answer.get0::<i32>()?; |
|
|
|
let result: i32 = answer()?; |
|
|
|
println!("Answer: {}", result); |
|
|
|
# Ok(()) |
|
|
|
# } |
|
|
|
``` |
|
|
|
|
|
|
|
The names of the WebAssembly module's imports and exports can be discovered by means of module's corresponding methods. |
|
|
|
The names of the WebAssembly module's imports and exports can be discovered by |
|
|
|
means of module's corresponding methods. |
|
|
|
|
|
|
|
# src/main.rs |
|
|
|
|
|
|
|
```rust |
|
|
|
```rust,no_run |
|
|
|
# extern crate wasmtime; |
|
|
|
use std::error::Error; |
|
|
|
use std::fs::read; |
|
|
|
use wasmtime::*; |
|
|
|
|
|
|
|
fn main() { |
|
|
|
fn main() -> Result<(), Box<dyn Error>> { |
|
|
|
let store = Store::default(); |
|
|
|
|
|
|
|
let wasm = read("hello.wasm").expect("wasm file"); |
|
|
|
let wasm = read("hello.wasm")?; |
|
|
|
|
|
|
|
let module = Module::new(&store, &wasm).expect("wasm module"); |
|
|
|
let instance = Instance::new(&module, &[]).expect("wasm instance"); |
|
|
|
let module = Module::new(&store, &wasm)?; |
|
|
|
let instance = Instance::new(&module, &[])?; |
|
|
|
|
|
|
|
let answer = instance.get_export("answer").expect("answer").func().expect("function"); |
|
|
|
let result = answer.call(&[]).expect("success"); |
|
|
|
let result = answer.call(&[])?; |
|
|
|
println!("Answer: {:?}", result[0].i32()); |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
``` |
|
|
|