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

Disable default marshalling for bool #65749

Merged
merged 4 commits into from
Mar 3, 2022

Conversation

jkoritzinsky
Copy link
Member

For consistency with the new default rules for bool fields in value types, update the default marshalling for bool parameters and return values to be 1-byte non-normalized instead of 4-byte normalized.

I've tried to split up the commits to make them easier to review:

  1. updates all existing source-generated P/Invokes to have explicit [MarshalAs(UnmanagedType.Bool)] attributes to preserve the current default behavior.
  2. updates the default marshalling rules in the generator.
  3. updates the conversion code-fix.
  4. updates the compatibility doc.

@ghost
Copy link

ghost commented Feb 23, 2022

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

Issue Details

For consistency with the new default rules for bool fields in value types, update the default marshalling for bool parameters and return values to be 1-byte non-normalized instead of 4-byte normalized.

I've tried to split up the commits to make them easier to review:

  1. updates all existing source-generated P/Invokes to have explicit [MarshalAs(UnmanagedType.Bool)] attributes to preserve the current default behavior.
  2. updates the default marshalling rules in the generator.
  3. updates the conversion code-fix.
  4. updates the compatibility doc.
Author: jkoritzinsky
Assignees: -
Labels:

area-System.Runtime.InteropServices, source-generator

Milestone: -

@AaronRobinsonMSFT
Copy link
Member

AaronRobinsonMSFT commented Feb 23, 2022

I agree with this change, but I think a discussion with other stakeholders is warranted due to the scope of impact. This sort of semantic change between the built-in and new source generators is, in my opinion warranted, but let's see if there is any non-obvious concern for other heavy interop users.

/cc @dotnet/interop-contrib @jkotas @MichalStrehovsky @stephentoub @JeremyKuhne

@jkotas
Copy link
Member

jkotas commented Feb 23, 2022

1-byte default for bool is likely wrong more than 50% of the time and it will have to be overridden most of the time. Given that, I think it would be better to make the marshaling directive for bool mandatory.

It matches the approach that we took with string marshaling. There is no great default for string marshaling and so we require it to be always specified explicitly.

@jkotas
Copy link
Member

jkotas commented Feb 23, 2022

We may want to introduce a new BOOL type (exact name and shape subject to negotiation - for example, it can be enum BOOL that we use internally in some places) to make the typical bool marshaling patterns less verbose and more efficient.

@elinor-fung
Copy link
Member

@jkoritzinsky had also suggested exposing a BOOL type - similar to our internal enum - last Friday. Definitely agree it would be a good idea (just don't think any of us have gotten to actually proposing it).

@tannergooding
Copy link
Member

tannergooding commented Feb 23, 2022

We may want to introduce a new BOOL type (exact name and shape subject to negotiation - for example, it can be enum BOOL that we use internally in some places) to make the typical bool marshaling patterns less verbose and more efficient.

This is another scenario where, in my opinion, having some [TransparentStructAttribute] would be beneficial. Having an enum BOOL is ok but it isn't extensible, you can't ever expose additional operators or methods, and it's only one of many types where a regular wrapper struct isn't possible. Users will have to find/discover it and the name will conflict with similar types exposed in other libraries already.

You have cases like BOOL, COLORREF, LPARAM, WPARAM, and all the HANDLE types on Win32. You have types like VkBool32 and VkBuffer for Vulkan as an xplat API. You have similar examples in various Linux or MacOS centric APIs.

There are plenty of common cases, and a near endless number of other scenarios, where in C users have some typedef primitive Name; and where for clarity, readability, or even to expose functionality that only makes sense for Name and not primitive in general you want to provide some kind of wrapper in C# and to have it ultimately be treated as blittable.

TransparentStructAttribute (or a better name) would allow the same scenario as it does in Rust (repr(transparent)) and would allow users to define their own wrappers that fit the needs of their libraries and for the needs of their customers. It would allow the current special-casing of CLong, CULong, and NFloat to be generalized around such an attribute instead and for users to fill the gap on their own in the future.

@jkotas
Copy link
Member

jkotas commented Feb 23, 2022

Transparent structures can be implemented with a bit of boilerplate code already: https://github.com/dotnet/runtime/blob/main/docs/design/libraries/DllImportGenerator/StructMarshalling.md#special-case-transparent-structures. We can make the source generator generate this boilerplate for you if it moves the needle enough.

@jkoritzinsky jkoritzinsky force-pushed the explicit-boolean-marshalling branch 2 times, most recently from 3e84e5e to f70f4ca Compare February 24, 2022 23:47
@jkoritzinsky jkoritzinsky changed the title Change default bool marshalling for generated P/Invokes to be 1-byte non-normalized Disable default marshalling for bool Feb 24, 2022
@jkoritzinsky
Copy link
Member Author

I've updated this pr to disable default marshalling for bool instead of changing the default.

@elinor-fung
Copy link
Member

Generator changes look good to me. We should also run libraries outerloop (once the innerloop is green).

@jkoritzinsky jkoritzinsky force-pushed the explicit-boolean-marshalling branch 2 times, most recently from 21f809c to e8e7884 Compare March 2, 2022 21:06
@jkoritzinsky
Copy link
Member Author

Failures are #66100

@jkoritzinsky jkoritzinsky merged commit 922777a into dotnet:main Mar 3, 2022
@jkoritzinsky jkoritzinsky deleted the explicit-boolean-marshalling branch March 3, 2022 04:57
@ghost ghost locked as resolved and limited conversation to collaborators Apr 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Runtime.InteropServices source-generator Indicates an issue with a source generator feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants