Rust/WinRT coming soon

My rust adventure continues as I have been furiously working on Rust/WinRT for the last five months or so. I am indebted to Ryan Levick for patiently answering all of my questions and also jumping in and getting deeply involved in the project early on. I am also looking forward to opening it up to the community as soon as possible. Even then, it will be early days and much still do. I remember chatting with Martyn Lovell about this a few years ago and we basically agreed that it takes about three years to build a language projection. Naturally, you can get value out of it before then but that’s what you need to keep in mind when you consider completeness.

Still, I’m starting to be able to make API calls with Rust/WinRT and its very satisfying to see this come together. So, I’ll leave you with a sneak peek to give you sense of what calling Windows APIs looks like in Rust. Here’s the venerable Windows.Foundation.Uri class:

use windows::foundation::*;

let uri = Uri::create_uri("")?;
assert!(uri.domain()? == "");
assert!(uri.port()? == 443);
assert!(uri.to_string()? == "");

Immediately you’ll notice this looks far more like Rust (if you’re familiar with Rust) than it looks like C++ or C#. Notice the snake_case on module and method names and the ? operator for error propagation. The Uri class has a constructor that’s implemented by a factory method called CreateUri. Since Rust lacks constructors, we simply take that CreateUri method and project it as create_uri to conform to Rust’s naming conventions. The to_string method comes from the IStringable interface that the Uri class implements. Even though Rust doesn’t support type inheritance, Rust/WinRT ensures that you get the same classy type system that WinRT is built on. Under the hood, Rust/WinRT will naturally use QueryInterface to query for the IStringable interface so that it just works. You can also expect the same on-the-metal performance and efficiency as you do from C++/WinRT.

Here’s another example using the Windows.ApplicationModel.DataTransfer namespace to copy some value onto the clipboard:

use windows::application_model::data_transfer::*;

let content = DataPackage::new()?;


Here we’re calling the DataPackage’s default constructor, but of course Rust doesn’t have constructors. The default constructor is thus replaced with the conventional new method.

And finally, here’s an example of using the Windows.UI.Composition API:

use windows::foundation::numerics::*;
use windows::ui::composition::*;
use windows::ui::*;

let compositor = Compositor::new()?;
let visual = compositor.create_sprite_visual()?;
let red = Colors::red()?;
assert!(red == Color { a: 255, r: 255, g: 0, b: 0 });

let brush = compositor.create_color_brush_with_color(red)?;

visual.set_offset(Vector3 { x: 1.0, y: 2.0, z: 3.0, })?;
assert!(visual.offset()? == Vector3 { x: 1.0, y: 2.0, z: 3.0 });

Here you can see we’re creating a Compositor. We use the compositor to create a sprite visual with a red brush and then set the visual’s offset. This seems simple, but that’s a testament to the sheer amount of work that’s already gone into Rust/WinRT to make it seem so natural and native to Rust. The Composition API is one of only two type hierarchies in the Windows API and requires special attention to get right in any language projection, let alone a language that lacks traditional inheritance.

My point here is not to claim these are superb APIs. There may well be a better way to do these tasks in Rust. The point is that Rust/WinRT lets you call any Windows API past, present, and future using code generated on the fly directly from the canonical metadata describing the API and right into your Rust package where you can call them as if they were just another Rust module.

I’m looking forward to sharing more about Rust/WinRT.

15 thoughts on “Rust/WinRT coming soon

  1. Alexander

    Awesome news! 😁 Can’t wait to try it in action!

    One question: Do you already have a plan for projecting Windows.UI namespace? I mean the inheritance and authoring UI components. What would be your preferred approach to this?

  2. Krzysztof Lesiak

    I’m very much excited about this! Looking forward to trying it in action. 🙂

    Did you run into issues with mapping certain WinRT constructs/classes to Rust? I’m thinking about something the borrow checker would complain about, i.e. needing shared and mutable references at the same time because of the way a WinRT API was originally designed.

  3. Sam

    Dear Kenny,

    What is Microsoft’s continuity plan for these Rust endeavors?

    For example, what will Microsoft do if Mozilla were to fail financially and be no longer able to support Rust’s development and maintenance?

    Or for example, what will Microsoft do if Mozilla takes Rust in a direction that does not align with the needs of Microsoft and its users?

    Will Microsoft fork Rust and continue to maintain it without Mozilla’s involvement?


    1. Kenny Kerr Post author

      Hi Sam, our goal is to bring the Windows Runtime to more languages to make it easier for developers of different stripes to write apps and components for Windows. We are however only interested in standard languages and compilers. Personally, I joined Microsoft because I thought that C++/CX was a terrible idea and that we needed a standard C++ solution so I created C++/WinRT. The same goes for Rust. Regarding Rust’s future, I can only speculate, but this is promising.

  4. 紅樓鍮

    I notice that all WinRT methods return `Result`s. Have you tried to determine at source-code-generation-time if a method may or may not actually fail and model the return type accordingly? `Colors::Red()` returning a `Result` in particular looks bizarre, considering that aggregate-initializing a `Color` in contrast cannot fail.

    1. Kenny Kerr Post author

      The only thing that language projections can go on is the metadata describing the various APIs. Unless those APIs say otherwise, the code generation cannot know whether some API will fail. We might know intuitively that `Red` could not possibly fail, but the code generator doesn’t know that. For all it knows, the implementation might decide to return an error if `Red` is called on Tuesdays. I did however recently add a new WinRT attribute that APIs can use to indicate that a certain API cannot fail, but the `Colors` API is too old to benefit from that.

      Of course in this case, you can just create a `Color` struct with A,R,G,B values instead of calling the API. The use of the `Colors` API was just for illustration purposes. 🙂

      1. 紅樓鍮

        Yeah. The fact that WinRT and xlang in general made the unfortunate design decision to model its API structure almost solely after C# is too true for a project that have cross-language interfacing as one of its core objectives.

        As more and more language projections are developed, WinRT APIs will have to standardize even more well-known attributes to specify contracts and invariants that a variety of different programming languages are able to utilize. A lot of WinRT “classes”, for example, are actually data records that, if decorated in the metadata, may be projected into languages as some form of pure data type. This would be essential for a Haskell projection, a language that differentiates side-effectful computations from pure ones. C++ and Rust and even C# could project them as bare `struct`s.

      2. Kenny Kerr Post author

        There will always be trade-offs when trying to come up with a single metadata representation to support multiple languages. WinRT’s choice of ECMA-335 is as good as any and works quite well in practice. Language projections are free to map types uniquely so there is a lot of freedom to innovate and optimize for a given language.

    1. Kenny Kerr Post author

      I don’t know about soon, but yes that’s what this would enable. 🙂 The first step is language projection support and that’s what this project is focused on right now.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s