Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide vtables from COM and WinRT as raw bindings #2514

Closed
stuntman11 opened this issue May 22, 2023 · 6 comments
Closed

Provide vtables from COM and WinRT as raw bindings #2514

stuntman11 opened this issue May 22, 2023 · 6 comments
Labels
question Further information is requested

Comments

@stuntman11
Copy link

stuntman11 commented May 22, 2023

Motivation

I recently wanted some raw bindings for mmdevice and mme api so I used the windows-sys crate as a dependency. It all went smoothly in the beginning but soon I needed to construct and call the MMDeviceEnumerator COM Interface. From there on it was a huge pain. The windows-sys crate as stated in "Choosing between the windows and windows-sys crates" does not support COM in favor of compilation speed. At first I just copied the required vtables provided by the windows crate into my project but that was really unpleasant experience. I still wanted raw bindings but had no easy access to the vtables for COM Interfaces. So I chose to scrap the idea and just import both windows and windows-sys and use the windows crate whenever I need COM.

Why is there no crate with the full set of raw bindings for the windows apis?

I think this is a big issue for usability, especially for other rust libraries. I have seen some examples on the way (e.g cpal PR#778) which also just copy the vtables into their source code to interact with COM while using windows-sys. The windows crate provides a lot of convenient wrappers but I would still appreciate to have a complete raw binding crate like other C-style apis for rust provide. What are your thoughts?

Drawbacks

I am not sure if this would require a new crate. I would expected it from the windows-sys crate because the "sys" suffix seems to be used for raw binding libraries but as stated COM and WinRT were explicitly removed to improve compilation speed.

Rationale and alternatives

No response

Additional context

This also relates to #2187

@stuntman11 stuntman11 added the enhancement New feature or request label May 22, 2023
@kennykerr kennykerr added question Further information is requested and removed enhancement New feature or request labels May 22, 2023
@kennykerr
Copy link
Collaborator

Rust doesn't directly support virtual functions the way that C++ does (and required by COM) so simply providing the "raw" bindings does not in practice help very much to call COM or WinRT APIs since a lot of code is still required to deal with calling conventions, membership, vtable indirection, queries, and ownership. As such, adding all of that to the windows-sys crate would negate the benefits of the crate.

Your best bet it is to use the windows crate as I described here:

https://kennykerr.ca/rust-getting-started/windows-or-windows-sys.html

If the compilation cost is too high due to the overall size of the windows crate, standalone code generation is provided and lets you generate just the bindings you need:

https://kennykerr.ca/rust-getting-started/standalone-code-generation.html

This is what @Jake-Shadle, the author of the PR you cite, indicated he would use for such scenarios (#1720) so it's unclear why he's taken the approach of adding all that hand-rolled/copied code into the PR. That seems entirely unmaintainable.

@stuntman11
Copy link
Author

stuntman11 commented May 22, 2023

For me its not so much about the compilation time, but more about the idea that bindings should provide a minimal interop to C/C++ even for virtual functions. In this case it would translate to a crate for rust wrapped types (windows) and a crate with only the minimum but still complete set of unsafe interop with vtables, structs and no altered function parameters. An example are these C# interop packages (P/Invoke) that basically act like a bare metal bridge between C# and C/C++.

I do see that this negates the idea of windows-sys and thus should not be implemented into the crate. But I still think such a separation would be beneficial and I don't understand how windows-bindgen would help me in my specific case. Is there a more in depth documentation on that?

@kennykerr
Copy link
Collaborator

I appreciate that the "idea" of raw COM bindings might be appealing in Rust, but they're not very practical due to the amount of extra scaffolding required to actually make them work in practice. I continue to optimize and streamline the windows crate and its code gen to eliminate or minimize the real or perceived overhead, but providing another alternative doesn't seem beneficial at this point.

@kennykerr
Copy link
Collaborator

Anyway, closing for now but feel free to keep the conversation going!

@kennykerr kennykerr closed this as not planned Won't fix, can't repro, duplicate, stale May 22, 2023
@a1phyr
Copy link

a1phyr commented May 23, 2023

Could there be a middle ground with a separate crate for COM support ? Something like https://lib.rs/crates/com or https://lib.rs/crates/com-rs.

It would not weigh in on windows-sys and would be far lighter than using windows.

@kennykerr
Copy link
Collaborator

The windows-implement and windows-interface crates are essentially equivalent to the old com crate. They are dependencies of the windows crate but could in theory be standalone:

https://crates.io/crates/windows/dependencies

But that's different to providing the pre-generated bindings for existing COM and WinRT interfaces in the Windows SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants