Documenting WinUI support progress

Here I will be documenting my attempts to get WinUI 3.0 working with Swift. As about half(?) of WinUI is written in C++, I'm making the tentative assumption that this is possible (GitHub lists that half of the repository is C++ and the other half is C#; I'm guessing that this is to provide support for both languages, but I could be very wrong). The broad steps I'm foreseeing are:

  1. Find the header path for <winrt/Microsoft.UI> as a starting point
  2. Create a C shim around the whole library
  3. Create a module.modulemap for the shim
  4. ???
  5. Profit

Step 2 is where I'm lacking experience, but hey, there's no better time to do loads of manual data entry and read languages you only kind of understand when you're sheltering in place, right?

I'm confident given enough time (i.e. months at minimum) I can crack this, but it may take a while and I will likely resort to dirty hacks to get stuff working.

12 Likes

<winrt/Microsoft.UI> doesn't seem to be in the usual SDK path. However, I was able to get it to download(?)/generate by creating a new UWP application in Visual Studio. It gets put in the Generated Files folder of the project.


Adding the following to the module.modulemap in {SDK}\um\:

  module WinUI {
    header "../cppwinrt/winrt/Windows.UI.h"
    export *

    link "WinUI.Lib"
  }

and adding the compiler flag -Xfrontend -enable-cxx-interop results in a whole lot of errors from the imported headers, as expected. Note that that's Windows.UI, not Microsoft.UI.

Is WinUI based on WinRT? If so, then targeting interop with COM, winmds, and WinRT's IInspectable interface seems more tractable than general C++ interop, and could give you access to the bits of the system written in C++, C#, and JS through the existing runtime bridges.

3 Likes

Would getting Swift to parse winmds be a first step to that? I could also write a C/Swift wrapper around IInspectable, which is admittedly more feasible than a wrapper around the entire architecture.

Yeah, one approach might be to try to parse winmds and generate Swift interfaces from them; since a COM type is more or less a pointer to a pointer to a struct full of function pointers, that should be representable as generated Swift types. You would still need to manually AddRef/Release/QueryInterface COM objects, though. In the long view, it would be cool if eventually the winmd importer could be integrated into the Swift compiler, like the ObjC pointer is now, so that COM types could be treated as automatically refcounted types, interfaces could be imported as Swift protocols, and Swift code could implement COM interfaces and automatically generate IInspectable/IDispatch metadata.

Interesting. In that case, I'll start work on a winmd parser. It's all standardized in ECMA-335, so I hopefully won't run into too many speedbumps with the format (famous last words).

1 Like

Microsoft has a Windows bridge for iOS. It's open-sourced on GitHub. Although it's for Cocoa Touch APIs, it might help with porting other Cocoa APIs in general.