You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The process of creating host functions and passing them as imports to a WebAssembly module suffers from several ergonomics issues:
If a function wants to access state, you need to create an explicit type that implements WasmEnv and use something like Function::new_native_with_env(). If functions want to share state then they'll typically need to wrap the env (or just some of its fields) in Arc<Mutex<_>>
The host functions themselves are very low-level and each host function needs to be added to the ImportsObject explicitly
All argument marshalling needs to be done manually when inside the host function
Argument marshalling requires unsafe for all but the most trivial host functions
This results in a lot of boilerplate and error-prone unsafe code
Because exposing a function from the host to the guest is quite an involved process we've found there is a real disincentive to changing existing APIs or creating detailed interfaces
This also means engineers will tend to hack around poor design decisions in the host or guest instead of fixing the problem by changing/replacing the host function
Additionally, if you need to use multiple WebAssembly runtimes (e.g. because Wasmer doesn't support a platform you want to target - #2580, #217) all of this boilerplate needs to be duplicated and adapted to fit the other WebAssembly runtime.
Proposed solution
From the end user's perspective, the process of defining and registering host functions should be as seamless as possible.
Ideally, you could use a handful of custom derives and add an attribute to a trait definition, and the library will generate everything else.
Using items exported by the WebAssembly module could be done by accepting them as arguments to the trait's methods. For example:
traitFoo{fndo_something_with_callback(&mutself,#[export]memory:&Memory,#[export(name = "real_name", alias = "_real_name)]callback:&mutNativeFunc<(i32,i32),i32>);}
Alternatives
Interface Types
We can't touch on the topic of interop between guest and host without mentioning the Interface Types Proposal.
Ideally, the code being generated by these macros will be completely hidden from the user and could use interface types as the underlying mechanism for passing objects/functions around, or we could use manual code as a polyfill.
WITX + Wiggle
The wasmtime project has a crate called wiggle which will generate much the same code, except it uses a WITX file to define the interface instead of a Rust trait.
I raised the question of adding wasmer support to wiggle in the past, but it sounds like their end goal is to specialize wiggle to work with just wasmtime because supporting multiple runtimes added a lot of engineering work:
Wasmtime has nearly subsumed Lucet in our (Fastly) production use. Once we have EOL'd Lucet, we intend to refactor wiggle to specialize it to just work with Wasmtime. Having wiggle factored to support two different runtimes makes it harder to read & write, among other design compromises we've been forced into. So, wiggle may end up evolving so that it is not viable to use on a different engine.
Another project which has done something similar is wasm-bindgen. Ideally, we could reuse a lot of their lessons and tricks with our own implementation, while also designing things in a way that doesn't lock users into a single runtime.
The text was updated successfully, but these errors were encountered:
I've added wasmer support to witx-bindgen in this branch. Give it a try and see if this is what you are looking for. Note that this is still a preview and the API of the generated bindings is still subject to change.
You'll have to use the master branch of wasmer for this to work since it uses some features that are not yet in the latest release. Use these in Cargo.toml:
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Motivation
The process of creating host functions and passing them as imports to a WebAssembly module suffers from several ergonomics issues:
WasmEnv
and use something likeFunction::new_native_with_env()
. If functions want to share state then they'll typically need to wrap the env (or just some of its fields) inArc<Mutex<_>>
ImportsObject
explicitlyunsafe
for all but the most trivial host functionsunsafe
codeSee here for an example that implements these host functions.
Additionally, if you need to use multiple WebAssembly runtimes (e.g. because Wasmer doesn't support a platform you want to target - #2580, #217) all of this boilerplate needs to be duplicated and adapted to fit the other WebAssembly runtime.
Proposed solution
From the end user's perspective, the process of defining and registering host functions should be as seamless as possible.
Ideally, you could use a handful of custom derives and add an attribute to a trait definition, and the library will generate everything else.
For example, imagine this input:
Which would then expand to something like this:
Lots of boilerplate that programmers would normally write manually.
Using items exported by the WebAssembly module could be done by accepting them as arguments to the trait's methods. For example:
Alternatives
Interface Types
We can't touch on the topic of interop between guest and host without mentioning the Interface Types Proposal.
Ideally, the code being generated by these macros will be completely hidden from the user and could use interface types as the underlying mechanism for passing objects/functions around, or we could use manual code as a polyfill.
WITX + Wiggle
The wasmtime project has a crate called
wiggle
which will generate much the same code, except it uses a WITX file to define the interface instead of a Rust trait.I raised the question of adding
wasmer
support towiggle
in the past, but it sounds like their end goal is to specializewiggle
to work with justwasmtime
because supporting multiple runtimes added a lot of engineering work:Additional context
Another project which has done something similar is
wasm-bindgen
. Ideally, we could reuse a lot of their lessons and tricks with our own implementation, while also designing things in a way that doesn't lock users into a single runtime.The text was updated successfully, but these errors were encountered: