Stream: wit-bindgen

Topic: understanding status of resources


view this post on Zulip Christoph Brewing (Jun 26 2023 at 13:37):

I do observe that C++ is not among the languages for which host bindings can be generated with wit-bindgen. I would like to know the reason(s) for this: is it just a matter of priority? Is there a conceptual problem providing these or are there still other reasons?

view this post on Zulip Alex Crichton (Jun 26 2023 at 14:43):

Nah just priority! The Wasmtime C++ bindings are for the core wasm layer and right now no one's implemented the C++ side of things. One option would be to add component support to Wasmtime's C API (a pretty big undertaking), and another option would be to build a C++ bindings generator targetting the current core wasm API (but this is limited to running a single component, so limited in its functionality). In any case no fundamental reason C++ can't have this, just a matter of time and effort

view this post on Zulip Adam Crain (Jun 26 2023 at 15:34):

First post here. I'm interested in using WASM+WIT to create a plugin ecosystem for an application in industrial automation. I have gotten some basic demos running using Rust as the host and guest using wasmtime + wit-bindgen. I realize that WIT is early days still.

A few questions:

1) I'm struggling a bit with terminology. Reading the docs on WIT, it appears that resources are a way of passing an abstract/opaque type (i.e. something that has methods but no data fields like a class or interface in OOP languages ) back and forth between the guest and the host. Am I this correctly?
2) Am I understanding correctly that wit-bindgen does not yet support resources/handles?
3) Is there any estimate of when prototype support might be available?
4) Is there any way of emulating this kind of pattern ATM in WIT?

Here's a simple example. From the Host, I'd like my interface to the guest to allow the ability to create an instance of something opaque.


// 'plugin' is a component instance

// create an another opaque
let mut instance: <opaque type> = plugin.create(<bytes>, <opaque type>)?;
...
// call methods on the opaque type once created
instance.tick()


view this post on Zulip Alex Crichton (Jun 26 2023 at 15:42):

Reading the docs on WIT, it appears that resources are a way of passing an abstract/opaque type ... back and forth between the guest and the host. Am I this correctly?

Correct yeah, think of it sort of like a file descriptor if that helps.

Am I understanding correctly that wit-bindgen does not yet support resources/handles?

Correct, although it's what I'm currently working on!

Is there any estimate of when prototype support might be available?

Hopefully soon.

Is there any way of emulating this kind of pattern ATM in WIT?

Not currently, no.

view this post on Zulip Adam Crain (Jun 26 2023 at 15:43):

Thanks Alex. That's all extremely helpful! Thanks for your insights.

view this post on Zulip Notification Bot (Jun 26 2023 at 16:27):

Adam Crain has marked this topic as resolved.

view this post on Zulip Cole Nelms (Jun 26 2023 at 19:54):

Do we have a time estimate on new languages support?

view this post on Zulip Notification Bot (Jun 26 2023 at 19:54):

Cole Nelms has marked this topic as unresolved.

view this post on Zulip Robin Brown (Jun 26 2023 at 20:03):

@Cole Nelms that's a very broad question. Do you mean "host language Wasmtime support for new languages" or "guest language support in their respective toolchains" or something else?

view this post on Zulip Christof Petig (Jun 27 2023 at 14:10):

Christoph Brewing said:

I do observe that C++ is not among the languages for which host bindings can be generated with wit-bindgen. I would like to know the reason(s) for this: is it just a matter of priority? Is there a conceptual problem providing these or are there still other reasons?

I have c++ host bindings for wamr generation working for my small necessary subset of wit in my fork at https://github.com/cpetig/wit-bindgen, that might work as a starting point. I am currently extending it to guest bindings and more types as well, but I didn't figure out how to best share the most amount of code across generators, yet.

A language binding generator for WebAssembly interface types - GitHub - cpetig/wit-bindgen: A language binding generator for WebAssembly interface types

view this post on Zulip Christoph Brewing (Jun 28 2023 at 07:45):

@Christof Petig thank you for sharing that, Christof! That may become very interesting for me.

view this post on Zulip Gordon Smith (Jul 03 2023 at 15:21):

Alex Crichton said:

Nah just priority! The Wasmtime C++ bindings are for the core wasm layer and right now no one's implemented the C++ side of things. One option would be to add component support to Wasmtime's C API (a pretty big undertaking), and another option would be to build a C++ bindings generator targetting the current core wasm API (but this is limited to running a single component, so limited in its functionality). In any case no fundamental reason C++ can't have this, just a matter of time and effort

Is the guts of this essentially implementing a C++ ABI equivalent to: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md?

Repository for design and specification of the Component Model - component-model/design/mvp/CanonicalABI.md at main · WebAssembly/component-model

view this post on Zulip Alex Crichton (Jul 03 2023 at 15:25):

No the canonical ABI is for how Wasmtime interacts with components, where the Wasmtime C API is for how C hosts interact with Wasmtime written in Rust. Wasmtime has native Rust APIs for interacting with the component model, and these are what would be surfaced in the C API and they handle the canonical abi internally

view this post on Zulip Gordon Smith (Jul 03 2023 at 15:43):

At the moment I am testing wasmtime in a c++ host with wit generated guest bindings and am just getting to the more interesting parts (strings and data structs / records etc.) so had been porting those functions as needed (the c++ is a runtime for a domain specific language, so having wit generate the c++ host wouldn't be that useful). I just wanted to sanity check that there isn't something about to be released, which would make it a complete waste of time (the ABI porting has been mostly painless to date)?

view this post on Zulip Alex Crichton (Jul 03 2023 at 15:48):

Ah sorry, I misunderstood! If you're targetting the core wasm API layer of Wasmtime then yes you'd need to implement the canonical ABI. That being said "exploding" a component into its core wasms and running them is not trivial

view this post on Zulip Gordon Smith (Jul 03 2023 at 16:26):

I am somewhat assuming that c/c++ support will overtake my wrapper at some point in the future (but am keen to get something in place now).

view this post on Zulip Adam Crain (Jul 06 2023 at 02:09):

Little followup to my original post. I'm guessing that the answer is also "wait for Resources".

Is there currently a way to get state/mutability in the Guest at all? All of the trait methods on the host side of things take &mut self whereas the Guest traits are just static methods. Is there any way to have state inside the Guest ATM?

From what I've read in the WIT docs it looks like resources address this issue, i.e. host calls a static function on the guest to create a resource, then it can call mutating methods on the resource.

view this post on Zulip Dan Gohman (Jul 06 2023 at 02:52):

Yes, resources will be the way to do this.

view this post on Zulip Christof Petig (Jul 06 2023 at 21:49):

I just realized that an easy way to quickly support resources would be to add a function to wit-bindgen which transforms the wit_parser::UnresolvedPackage by desugaring the resource to a handle type (u32) and its associated functions. This would immediately support ressources for all languages supported by wit-bindgen.

Then of course one could likewise transform future<t> into resource future-of-t { pollable: func(this: u32) -> pollable ; value: func(this: u32) -> t } and similarly for stream<t> and support these with already existing preview2 technology with little effort.

Did I miss something or could it really be that straightforward.

view this post on Zulip Till Schneidereit (Jul 06 2023 at 22:30):

the bottleneck for resources support is at this point much more the runtime implementation @Alex Crichton is working on than the guest bindings. @Joel Dice is making very good progress on those in this PR, and I'd hope that applying that work to other guest languages wouldn't be a prohibitive amount of work, either. If that turns out to be wrong, we could fall back to the kind of desugaring you mention

The generated code for C is pretty minimal, as you might expect. The Rust code provides a trait for each resource, while the trait representing the interface that contains resources gets an associ...

view this post on Zulip Christof Petig (Jul 07 2023 at 19:40):

Joel's work looks really promising (although the Rust code generator currently panics on the examples added by this MR :confused:) - but my primary motivation was getting a first support for future and stream ready - because I realized that I was doing the desugaring in WIT by hand for a lot of functions returning a "future" and this really hurts readability. And as indicated by https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#streams resources are the best approximation for typed streams available today.

view this post on Zulip Joel Dice (Jul 07 2023 at 21:40):

Hi Christof! Can you point me to the examples that are causing panics? I'd be happy to add them to the set of test cases (and fix the panics).

view this post on Zulip Christof Petig (Jul 07 2023 at 23:40):

The resources.wit and resource_alias.wit from tests/codegen paniced when creating rust code but worked with c (in debug mode)

view this post on Zulip Joel Dice (Jul 08 2023 at 01:40):

Ah, was the message something like "world export implementation required"? If so, that's trying to tell you that the generator needs to be told the name of the world trait implementation to use. One of the changes Alex and I decided to make was remove the export_*! macro that was previously used to specify the trait implementation and instead require that information up front (i.e. as command line options or generate! macro parameters, depending on how the generator is invoked).
So the complete command to generate the bindings for resources.wit, specifying the world, interface, and resource impls, would be something like:

wit-bindgen rust --world-exports MyResources --interface-exports exports=MyExports --resource-exports 'exports::x=MyX' tests/codegen/resources.wit

or, alternatively, you can tell the generator to generate stub impls instead:

wit-bindgen rust --stubs tests/codegen/resources.wit

You can see the discussion in the PR for details on _why_ we made this change, but in a nutshell the generics needed to support the export_*! macro with resources get hairy fast, and there wasn't a lot of value to it given that everything ends up monomorphic anyway.
That said, the UX could definitely need some work, i.e. wit-bindgen should print a friendly, helpful message when it needs more info instead of panicking. We could also consider making --stubs the default, at least when using the CLI. I'm open to suggestions!

view this post on Zulip Christof Petig (Jul 08 2023 at 06:55):

Thank you, I already suspected that it might require a different codegen configuration to work, but was unsure whether the default should panic.
I will take a closer look into implementing future polyfilled by resources in the coming days and make a more informed UX suggestion from there.

view this post on Zulip Christof Petig (Jul 09 2023 at 17:20):

I found that Joel's branch works really well, especially the Rust bindings. I was even able to define a function which consumes a resource (static consume: func(obj: own<my-object>)) and it was correctly mapped to call by value in Rust.

But some C bindings use a different module name __import_module__("test_example_my_interface"), __import_name__("[resource-drop-own]my-object") and __import_module__("my_world"), __import_name__("[resource-drop-borrow]my-object") (I guess the Rust module "test:example/my-interface" is more correct) .
Is there a description on how these methods should be named? I looked into WIT.md and CanonicalABI.md but didn't find them there.


Last updated: Dec 23 2024 at 12:05 UTC