Windows-rs: Add support for C-style unions

Created on 20 Jan 2021  路  20Comments  路  Source: microsoft/windows-rs

You might well be aware of this, internally, already. But the type win32::automation::VARIANT is not generated correctly.

I think it ends up, in Rust, as a struct containing just a bool called anonymous. Instead, it's an enum of sorts, with some weird named half-anonymous fields.

enhancement

Most helpful comment

Wow, that was a lot of work. The good news is that unions are working!

https://github.com/microsoft/windows-rs/tree/winmd/tests/unions/tests

I have some testing and polish to do before I can open a PR but it's looking good.

All 20 comments

Thanks Iain, the metadata and code generation for Win32 is still very experimental and there are various edge cases that aren't yet handled correctly. Structs with C-style unions in particular will take a while to sort out.

Fair enough! I was just 'jumping the gun' with excitement.

On the off chance you have the time to explain, I'd find it really interesting how you created the win32 metadata.

Another good example to test is D3D11_RENDER_TARGET_VIEW_DESC.

On the off chance you have the time to explain, I'd find it really interesting how you created the win32 metadata.

The metadata for Win32 APIs comes from this project: https://github.com/microsoft/win32metadata

Ah, thanks. I found that via your blog post from today, that you linked earlier.

Without unions directx 12 is unusable, so I hope this will be fixed soon! Great work so far.

Apologies to dogpile onto this request, but I hit this issue today as well.

I was (attempting) to write a basic wrapper around metadata handles (propsys.h stuff), and the fact the PROPVARAINT who's API expects you'll be able to inspect its tag & fields is represented by an opaque struct makes a lot of interactions with the metadata/properties API painful to impossible.

Got it, I'm going to get to this very soon. I know this is important for many scenarios.

OK, starting to work on this!

Types for testing:

  • Windows.Win32.WindowsColorSystem.WhitePoint
  • Windows.Win32.Automation.VARIANT
  • Windows.Win32.Direct3D11.D3D11_RENDER_TARGET_VIEW_DESC
  • Windows.Win32.DisplayDevices.DISPLAYCONFIG_VIDEO_SIGNAL_INFO
  • Windows.Win32.StructuredStorage.PROPVARIANT
  • Windows.Win32.SystemServices.OVERLAPPED

SLIST_HEADER is also notable as a top-level (named) union. It is also particularly problematic as it has a different layout depending on architecture.

DOT11_BSS_ENTRY_PHY_SPECIFIC_INFO is a simpler example of a top-level union.

I would also recommend having Windows.Win32.Direct3D12.D3D12_INDIRECT_ARGUMENT_DESC as a test case.

The c definition is

typedef struct D3D12_INDIRECT_ARGUMENT_DESC {
  D3D12_INDIRECT_ARGUMENT_TYPE Type;
  union {
    struct {
      UINT Slot;
    } VertexBuffer;
    struct {
      UINT RootParameterIndex;
      UINT DestOffsetIn32BitValues;
      UINT Num32BitValuesToSet;
    } Constant;
    struct {
      UINT RootParameterIndex;
    } ConstantBufferView;
    struct {
      UINT RootParameterIndex;
    } ShaderResourceView;
    struct {
      UINT RootParameterIndex;
    } UnorderedAccessView;
  };
} D3D12_INDIRECT_ARGUMENT_DESC;

This struct has multiple layers of nested types and is currently panicking on the struct-constants branch. It fails to find all types that are defined by the anonymous union in D3D12_INDIRECT_ARGUMENT_DESC, only finding the type for the VertexBuffer anonymous struct. The panic gets triggerd in Type::read_from_blob from TypeKind::Struct(nested[def.name().1].name.clone())

Yes I figured out how to get all the nested types. 馃槉

Sorry for the delay. The Win32 metadata has necessitated a pretty significant overhaul of the code generation. I'm busy wrapping that up - it should address a number of the open issues including support for unions.

Wow, that was a lot of work. The good news is that unions are working!

https://github.com/microsoft/windows-rs/tree/winmd/tests/unions/tests

I have some testing and polish to do before I can open a PR but it's looking good.

This is super exciting, Kenny. Thanks for your hard work!

You can tell from the emoji responses, that I am far from the only person looming forward to this.

I checked out the winmd branch this weekend and noticed that the fields in unions are generated with the hidden _abi types instead of the documented types. For example, PROPVARIANT_0 is defined with the field anonymous: PROPVARIANT_0_0_abi instead of anonymous: PROPVARIANT_0_0. Same thing happened for VARIANT. Don't know if that has been fixed since, but I wanted to bring it to your attention just in case.
image

It depends on whether the union is blittable. Rust doesn't support unions containing fields that need to be dropped. It doesn't affect unions where the fields don't need to be dropped. Those will just refer to the types directly. I'm still exploring options for dealing with this more naturally.

It may be as simple as wrapping those fields with std::mem::ManuallyDrop - I just need to test this to see what issues that may introduce.

Unions are now supported as of #577 - I'll leave this issue open until I come to some conclusion on unions with fields that should be dropped.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rylev picture rylev  路  4Comments

DJankauskas picture DJankauskas  路  3Comments

13r0ck picture 13r0ck  路  4Comments

rylev picture rylev  路  4Comments

bdbai picture bdbai  路  3Comments