You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
2.9 KiB

//! This is an example of working with mulit-value modules and dealing with
//! multi-value functions.
//!
//! Note that the `Func::wrap*` interfaces cannot be used to return multiple
//! values just yet, so we need to use the more dynamic `Func::new` and
//! `Func::call` methods.
// You can execute this example with `cargo run --example multi`
use anyhow::{format_err, Result};
use std::rc::Rc;
use wasmtime::*;
struct Callback;
impl Callable for Callback {
fn call(&self, args: &[Val], results: &mut [Val]) -> Result<(), Trap> {
println!("Calling back...");
println!("> {} {}", args[0].unwrap_i32(), args[1].unwrap_i64());
results[0] = Val::I64(args[1].unwrap_i64() + 1);
results[1] = Val::I32(args[0].unwrap_i32() + 1);
Ok(())
}
}
Migrate from failure to thiserror and anyhow (#436) * Migrate from failure to thiserror and anyhow The failure crate invents its own traits that don&#39;t use std::error::Error (because failure predates certain features added to Error); this prevents using ? on an error from failure in a function using Error. The thiserror and anyhow crates integrate with the standard Error trait instead. This change does not attempt to semantically change or refactor the approach to error-handling in any portion of the code, to ensure that the change remains straightforward to review. Modules using specific differentiated error types move from failure_derive and derive(Fail) to thiserror and derive(Error). Modules boxing all errors opaquely move from failure::Error to anyhow. Modules using String as an error type continue to do so. Code using unwrap or expect continues to do so. Drop Display implementations when thiserror can easily derive an identical instance. Drop manual traversal of iter_causes; anyhow&#39;s Debug instance prints the chain of causes by default. Use anyhow&#39;s type alias anyhow::Result&lt;T&gt; in place of std::result::Result&lt;T, anyhow::Error&gt; whenever possible. * wasm2obj: Simplify error handling using existing messages handle_module in wasm2obj manually maps cranelift_codegen::isa::LookupError values to strings, but LookupError values already have strings that say almost exactly the same thing. Rely on the strings from cranelift. * wasmtime: Rely on question-mark-in-main The main() wrapper around rmain() completely matches the behavior of question-mark-in-main (print error to stderr and return 1), so switch to question-mark-in-main. * Update to walrus 0.13 and wasm-webidl-bindings 0.6 Both crates switched from failure to anyhow; updating lets us avoid a translation from failure to anyhow within wasmtime-interface-types.
5 years ago
fn main() -> Result<()> {
// Configure our `Store`, but be sure to use a `Config` that enables the
// wasm multi-value feature since it's not stable yet.
println!("Initializing...");
let engine = Engine::new(Config::new().wasm_multi_value(true));
let store = Store::new(&engine);
// Compile.
println!("Compiling module...");
let module = Module::from_file(&store, "examples/multi.wat")?;
// Create external print functions.
println!("Creating callback...");
let callback_type = FuncType::new(
Box::new([ValType::I32, ValType::I64]),
Box::new([ValType::I64, ValType::I32]),
);
Remove `HostRef` from the `wasmtime` public API (#788) * Remove `HostRef` from the `wasmtime` public API This commit removes all remaining usages of `HostRef` in the public API of the `wasmtime` crate. This involved a number of API decisions such as: * None of `Func`, `Global`, `Table`, or `Memory` are wrapped in `HostRef` * All of `Func`, `Global`, `Table`, and `Memory` implement `Clone` now. * Methods called `type` are renamed to `ty` to avoid typing `r#type`. * Methods requiring mutability for external items now no longer require mutability. The mutable reference here is sort of a lie anyway since the internals are aliased by the underlying module anyway. This affects: * `Table::set` * `Table::grow` * `Memory::grow` * `Instance::set_signal_handler` * The `Val::FuncRef` type is now no longer automatically coerced to `AnyRef`. This is technically a breaking change which is pretty bad, but I&#39;m hoping that we can live with this interim state while we sort out the `AnyRef` story in general. * The implementation of the C API was refactored and updated in a few locations to account for these changes: * Accessing the exports of an instance are now cached to ensure we always hand out the same `HostRef` values. * `wasm_*_t` for external values no longer have internal cache, instead they all wrap `wasm_external_t` and have an unchecked accessor for the underlying variant (since the type is proof that it&#39;s there). This makes casting back and forth much more trivial. This is all related to #708 and while there&#39;s still more work to be done in terms of documentation, this is the major bulk of the rest of the implementation work on #708 I believe. * More API updates * Run rustfmt * Fix a doc test * More test updates
5 years ago
let callback_func = Func::new(&store, callback_type, Rc::new(Callback));
// Instantiate.
println!("Instantiating module...");
let instance = Instance::new(&module, &[callback_func.into()])?;
// Extract exports.
println!("Extracting export...");
let g = instance
.get_export("g")
.and_then(|e| e.func())
.ok_or(format_err!("failed to find export `g`"))?;
// Call `$g`.
println!("Calling export \"g\"...");
let results = g.call(&[Val::I32(1), Val::I64(3)])?;
println!("Printing result...");
println!("> {} {}", results[0].unwrap_i64(), results[1].unwrap_i32());
assert_eq!(results[0].unwrap_i64(), 4);
assert_eq!(results[1].unwrap_i32(), 2);
// Call `$round_trip_many`.
println!("Calling export \"round_trip_many\"...");
let round_trip_many = instance
.get_export("round_trip_many")
.and_then(|e| e.func())
.ok_or(format_err!("failed to find export `round_trip_many`"))?;
let args = vec![
Val::I64(0),
Val::I64(1),
Val::I64(2),
Val::I64(3),
Val::I64(4),
Val::I64(5),
Val::I64(6),
Val::I64(7),
Val::I64(8),
Val::I64(9),
];
let results = round_trip_many.call(&args)?;
println!("Printing result...");
print!(">");
for r in results.iter() {
print!(" {}", r.unwrap_i64());
}
println!();
assert_eq!(results.len(), 10);
assert!(args
.iter()
.zip(results.iter())
.all(|(a, r)| a.i64() == r.i64()));
Ok(())
}