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.

49 lines
1.8 KiB

//! Small example of how to instantiate a wasm module that imports one function,
//! showing how you can fill in host functionality for a wasm module.
// You can execute this example with `cargo run --example hello`
use anyhow::Result;
use wasmtime::*;
Migrate from failure to thiserror and anyhow (#436) * Migrate from failure to thiserror and anyhow The failure crate invents its own traits that don'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's Debug instance prints the chain of causes by default. Use anyhow's type alias anyhow::Result<T> in place of std::result::Result<T, anyhow::Error> 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 the initial compilation environment, creating the global
// `Store` structure. Note that you can also tweak configuration settings
// with a `Config` and an `Engine` if desired.
println!("Initializing...");
let store = Store::default();
Support parsing the text format in `wasmtime` crate (#813) * Support parsing the text format in `wasmtime` crate This commit adds support to the `wasmtime::Module` type to parse the text format. This is often quite convenient to support in testing or tinkering with the runtime. Additionally the `wat` parser is pretty lightweight and easy to add to builds, so it&#39;s relatively easy for us to support as well! The exact manner that this is now supported comes with a few updates to the existing API: * A new optional feature of the `wasmtime` crate, `wat`, has been added. This is enabled by default. * The `Module::new` API now takes `impl AsRef&lt;[u8]&gt;` instead of just `&amp;[u8]`, and when the `wat` feature is enabled it will attempt to interpret it either as a wasm binary or as the text format. Note that this check is quite cheap since you just check the first byte. * A `Module::from_file` API was added as a convenience to parse a file from disk, allowing error messages for `*.wat` files on disk to be a bit nicer. * APIs like `Module::new_unchecked` and `Module::validate` remain unchanged, they require the binary format to be called. The intention here is to make this as convenient as possible for new developers of the `wasmtime` crate. By changing the default behavior though this has ramifications such as, for example, supporting the text format implicitly through the C API now. * Handle review comments * Update more tests to avoid usage of `wat` crate * Go back to unchecked for now in wasm_module_new Looks like C# tests rely on this?
5 years ago
// Compile the wasm binary into an in-memory instance of a `Module`.
println!("Compiling module...");
let module = Module::from_file(store.engine(), "examples/hello.wat")?;
// Here we handle the imports of the module, which in this case is our
// `HelloCallback` type and its associated implementation of `Callback.
println!("Creating callback...");
let hello_func = Func::wrap(&store, || {
println!("Calling back...");
println!("> Hello World!");
});
// Once we've got that all set up we can then move to the instantiation
// phase, pairing together a compiled module as well as a set of imports.
// Note that this is where the wasm `start` function, if any, would run.
println!("Instantiating module...");
let imports = [hello_func.into()];
let instance = Instance::new(&store, &module, &imports)?;
// Next we poke around a bit to extract the `run` function from the module.
println!("Extracting export...");
let run = instance
Refactor (#1524) * Compute instance exports on demand. Instead having instances eagerly compute a Vec of Externs, and bumping the refcount for each Extern, compute Externs on demand. This also enables `Instance::get_export` to avoid doing a linear search. This also means that the closure returned by `get0` and friends now holds an `InstanceHandle` to dynamically hold the instance live rather than being scoped to a lifetime. * Compute module imports and exports on demand too. And compute Extern::ty on demand too. * Add a utility function for computing an ExternType. * Add a utility function for looking up a function&#39;s signature. * Add a utility function for computing the ValType of a Global. * Rename wasmtime_environ::Export to EntityIndex. This helps differentiate it from other Export types in the tree, and describes what it is. * Fix a typo in a comment. * Simplify module imports and exports. * Make `Instance::exports` return the export names. This significantly simplifies the public API, as it&#39;s relatively common to need the names, and this avoids the need to do a zip with `Module::exports`. This also changes `ImportType` and `ExportType` to have public members instead of private members and accessors, as I find that simplifies the usage particularly in cases where there are temporary instances. * Remove `Instance::module`. This doesn&#39;t quite remove `Instance`&#39;s `module` member, it gets a step closer. * Use a InstanceHandle utility function. * Don&#39;t consume self in the `Func::get*` methods. Instead, just create a closure containing the instance handle and the export for them to call. * Use `ExactSizeIterator` to avoid needing separate `num_*` methods. * Rename `Extern::func()` etc. to `into_func()` etc. * Revise examples to avoid using `nth`. * Add convenience methods to instance for getting specific extern types. * Use the convenience functions in more tests and examples. * Avoid cloning strings for `ImportType` and `ExportType`. * Remove more obviated clone() calls. * Simplify `Func`&#39;s closure state. * Make wasmtime::Export&#39;s fields private. This makes them more consistent with ExportType. * Fix compilation error. * Make a lifetime parameter explicit, and use better lifetime names. Instead of &#39;me, use &#39;instance and &#39;module to make it clear what the lifetime is. * More lifetime cleanups.
5 years ago
.get_func("run")
.ok_or(anyhow::format_err!("failed to find `run` function export"))?
.get0::<()>()?;
// And last but not least we can call it!
println!("Calling export...");
run()?;
println!("Done.");
Ok(())
}