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.

63 lines
2.2 KiB

use anyhow::Context;
use std::{fs, path::Path};
use wasmtime::{
component::{bindgen, Component, Linker},
Config, Engine, Result, Store,
};
// Generate bindings of the guest and host components.
bindgen!("convert" in "./examples/component/convert.wit");
struct HostComponent;
// Implementation of the host interface defined in the wit file.
impl host::Host for HostComponent {
fn multiply(&mut self, a: f32, b: f32) -> f32 {
a * b
}
}
struct MyState {
host: HostComponent,
}
/// This function is only needed until rust can natively output a component.
///
/// Generally embeddings should not be expected to do this programmatically, but instead
/// language specific tooling should be used, for example in Rust `cargo component`
/// is a good way of doing that: https://github.com/bytecodealliance/cargo-component
///
/// In this example we convert the code here to simplify the testing process and build system.
fn convert_to_component(path: impl AsRef<Path>) -> Result<Vec<u8>> {
let bytes = &fs::read(&path).context("failed to read input file")?;
wit_component::ComponentEncoder::default()
.module(&bytes)?
.encode()
}
fn main() -> Result<()> {
// Create an engine with the component model enabled (disabled by default).
let engine = Engine::new(Config::new().wasm_component_model(true))?;
// NOTE: The wasm32-unknown-unknown target is used here for simplicity, real world use cases
// should probably use the wasm32-wasip1 target, and enable wasi preview2 within the component
// model.
let component = convert_to_component("target/wasm32-unknown-unknown/debug/guest.wasm")?;
// Create our component and call our generated host function.
let component = Component::from_binary(&engine, &component)?;
let mut store = Store::new(
&engine,
MyState {
host: HostComponent {},
},
);
let mut linker = Linker::new(&engine);
host::add_to_linker(&mut linker, |state: &mut MyState| &mut state.host)?;
Redesign how component exports work (#8786) * Un-nest exports in a component This commit flattens the representation of exports in a component to make them more easily indexable without forcing traversal through the hierarchy of instance imports/exports to get there. * Guarantee type information on component exports Don&#39;t have it optional in some cases and present in others, instead ensure there&#39;s type information for all component exports immediately available. * Refactor how component instance exports are loaded This commit is a change to Wasmtime&#39;s public API for `wasmtime::component::Instance` that reorganizes how component exports are loaded. Previously there was a system where `Instance::exports()` was called that that was sort of &#34;iterated over&#34; in a builder-style pattern to acquire the actual export desired. This required lifetime trickery for nested instances and some unfortunate API bloat. The major downside of this approach is that it requires unconditional string lookups at runtime for exports and additionally does not serve as a great place to implement the semver-compatible logic of #8395. The goal of this refactoring is to pave the way to improving this. The new APIs for loading exports now look a bit more similar to what&#39;s available for core modules. Notably there&#39;s a new `Component::export_index` method which enables performing a string lookup and returning an index. This index can in turn be passed to `Instance::get_*` to skip the string lookup when exports are loaded. The `Instance::exports` API is then entirely removed and dismantled. The only piece remaining is the ability to load nested exports which is done through an `Option` parameter to `Component::export_index`. The way to load a nested instance is now to first lookup the instance with `None` as this parameter an then the instance itself is `Some` to look up an export of that instance. This removes the need for a recursive-style lifetime-juggling API from wasmtime and in theory helps simplify the usage of loading exports. * Update `bindgen!` generated structures for exports This commit updates the output of `bindgen!` to have a different setup for exports of worlds to handle the changes from the previous commit. This introduces new `*Pre` structures which are generated alongside the existing `Guest` structures for example. The `*Pre` versions contain `ComponentExportIndex` from the previous commit and serve as a path to accelerating instantiation because all name lookups are skipped. * Update test expectations for `bindgen!`-generated output * Review comments * Fix doc link
5 months ago
let convert = Convert::instantiate(&mut store, &component, &linker)?;
let result = convert.call_convert_celsius_to_fahrenheit(&mut store, 23.4)?;
println!("Converted to: {result:?}");
Ok(())
}