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

newtype vs type aliases for windows-sys? #1330

Closed
jstarks opened this issue Nov 16, 2021 · 14 comments · Fixed by #1331
Closed

newtype vs type aliases for windows-sys? #1330

jstarks opened this issue Nov 16, 2021 · 14 comments · Fixed by #1331
Labels
enhancement New feature or request

Comments

@jstarks
Copy link
Member

jstarks commented Nov 16, 2021

In windows-sys, could it make more sense to use type aliases instead of newtypes for things like BOOL and PWSTR? It's kind of inconvenient to have to spell out the types at every callsite, especially without the conversion methods available from the full windows crate.

The precedent in other low-level C wrapper crates (winapi, libc) seems to be to expose C typedefs as type aliases, so e.g. BOOL would just be an alias for c_int or i32, etc.

@kennykerr
Copy link
Collaborator

kennykerr commented Nov 16, 2021

Yes, I had considered that for the native typedefs. The concern is that this would make it a little less type safe, but perhaps that is less of a concern when you're using the windows-sys crate and everything is unsafe to begin with? For example, HANDLE would be isize and BOOL would be i32. It would certainly make code using windows-sys more concise.

@jstarks
Copy link
Member Author

jstarks commented Nov 16, 2021

In some cases it's probably a small safety win to have the newtypes, but it may also lead to losses due to the extra transmutes or casts for pointer parameters. E.g. if a function takes *const PWSTR and I have [*const u16], then I have to do slice.as_ptr() as *const PWSTR, which seems slightly more dangerous. My intuition would be to leave them out...

The other thing I found a little dangerous is that there's no PCWSTR, so we're actually losing const correctness for the pointer types. E.g. CreateFileW takes a PCWSTR, but in windows-sys it takes a PWSTR, which is a *mut u16. Not a real safety issue since it's just a pointer, but makes it harder to use the API correctly (I have to double check in the API docs that I really can past a const pointer).

Related, it's curious that HANDLE wraps isize and not *mut c_void, making it slightly more difficult to interoperate with std's RawHandle type.

All of this would probably be addressed by staying true to the C typedefs.

@kennykerr
Copy link
Collaborator

I like the no-frills nature and getting closer to the original Win32 API. The metadata also provides the necessary metadata for the const variant of PWSTR - I just need to plumb it through to Rust - its on my todo list:

image

@MarijnS95
Copy link
Contributor

@kennykerr Thanks for looking into const-correctness! That mutability cast on string literals has discomforted me more than I'd like 😁

@jstarks
Copy link
Member Author

jstarks commented Nov 16, 2021

Interesting that the const attribute looks top-level but actually applies what the pointer points to. What does metadata look like for an API taking a const pointer to PCWSTR (for example, for a list of strings).

@kennykerr
Copy link
Collaborator

kennykerr commented Nov 16, 2021

The metadata has come a long way and is pretty rich. I'd recommend grabbing ILSpy here:

https://github.com/icsharpcode/ILSpy/releases

You can then load the winmd for the win32 metadata and poke around. You can find the metadata that windows-rs uses here:

crates/deps/reader/default

@kennykerr kennykerr added the enhancement New feature or request label Nov 16, 2021
@kennykerr
Copy link
Collaborator

@jstarks I took that for a spin and I do like the results. The resulting code looks and feels a lot more like what it would in C/C++:

https://github.com/microsoft/windows-samples-rs/compare/sys-handles?expand=1

@jstarks
Copy link
Member Author

jstarks commented Nov 16, 2021

Cool. What do you think about additionally changing HANDLE to *mut c_void instead of isize? That will give back a little safety for handles (can't accidentally pass in some random integer) while also aligning with std::os::windows::io::RawHandle.

@kennykerr
Copy link
Collaborator

The Win32 metadata defines it as IntPtr rather than void* which means windows-rs maps it to isize rather than *mut c_void. If you think that's "more correct" then I'd prefer to push for the change in the metadata and then windows-rs will automatically map it to the appropriate underlying type. You can open an issue here:

https://github.com/microsoft/win32metadata/issues

@jstarks
Copy link
Member Author

jstarks commented Nov 16, 2021

Looks like there was some discussion several months ago: microsoft/win32metadata#21. I haven't had time to digest this yet, but it looks like perhaps it was changed based on feedback from .NET.

@kennykerr
Copy link
Collaborator

OK, let's figure out what that's about and go from there. We can always override that for Rust but I'd like to have a better understanding first.

@kennykerr
Copy link
Collaborator

Hmm, looks like Rust really really wants this to be a pointer:

https://doc.rust-lang.org/std/os/windows/raw/type.HANDLE.html

I may just override this for Rust and move on... It sure does make porting system code easier.

@kennykerr
Copy link
Collaborator

And this is now so: #1332

@kennykerr
Copy link
Collaborator

#1550 adds first-class types for PCSTR and PCWSTR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants