
Rust/WinRT Public Preview - steveklabnik
https://blogs.windows.com/windowsdeveloper/2020/04/30/rust-winrt-public-preview/
======
blinkingled
[https://github.com/robmikh/minesweeper-
rs](https://github.com/robmikh/minesweeper-rs) \- I just love how they
brilliantly avoided mixing up C++/COM things into this. Tough one to pull when
you're dealing with bindings for a foreign language. The code looks fairly
standard Rust (except maybe for the winrt::import that looks like Go?).

> If you are familiar with Rust, you will notice this looks far more like Rust
> than it looks like C++ or C#. Notice the snake_case on module and method
> names and the ? operator for error propagation.

Developing on and now for Windows just keeps getting better.

~~~
pathartl
It seems like they're doing all they can to get developers on their platform.
Not to establish Windows developers like they have in the past, but to have
others see Windows as just another platform.

We're reaching a revolution from moving from x86 to ARM and I think the more
Microsoft positions themselves like this, the less likely they are to be left
in some weird compatibility limbo.

As weird as this sounds, I feel more confident with Microsoft being able to do
a successful transition to ARM than Apple at this point.

~~~
pianoben
In fact, the _have_ transitioned to ARM, way back around the time of the first
Surface tablet. Windows and Office have been running on ARM since at least,
what, 2012?

~~~
loeg
Windows NT in 2000? I guess ARM was not a going concern at the time, but
Windows was remarkably portable in 2000 before the dark decade of more or less
exclusively Wintel.

~~~
zrm
[https://archive.org/details/Microsoft_Windows_NT_Server_Vers...](https://archive.org/details/Microsoft_Windows_NT_Server_Version_4.0_94373_Microsoft_1996)

"Disc contains code to run on Windows NT-compatible x86, Pentium, MIPS, R4x00,
Alpha, PowerPC and Pentium Pro systems"

------
oaiey
I start to understand the Windows team desire for this WinRT. You can flow
through time with these language bindings without being locked into a
programming language. .NET, JS, C++ and now Rust. That is seriously cool.

~~~
hota_mazi
It's been a reality on Windows for over 20 years, though. COM has made it
possible to write applications on Windows and integrate with pretty much
anything in it in any language with COM bindings.

Glad to see Rust is now one more such language.

~~~
badsectoracula
Yeah though... pretty much any natively compiled language and many
interpreted/VM-based languages can use the C ABI in any modern plaform anyway,
so what COM provides isn't so much the ability to use the same API from many
languages but a _dynamic_ object oriented approach for doing so.

After all it isn't like you can't use the Win32 API directly from Rust - or
any other language, e.g. Python.

~~~
kevingadd
The type libraries are a big part of why it's so successful - you can take a
typelib and auto-generate bindings, or manually generate your own bindings
based on what you see. If you look at the typelibs for a given GUID, you are
almost guaranteed that the API will match once you get a pointer back from a
QueryInterface call (sometimes people are naughty). This is nice because you
can compile all that in so the QueryInterface call is the only dynamic part of
it - everything else at runtime is just regular calls through a vtable. The
rigid nature of it means you can also reverse-engineer compiled code to figure
out the shape of a given interface's vtable even without a typelib (I've done
that a couple times).

This is why you were able to manipulate COM objects from VBScript and JScript
even though they were dynamic languages, and in fact VBScript could _define
new COM objects on the fly_ and then expose new methods and properties through
a COM interface called IDispatch. It's all just vtables once you do your
initial setup.

IIRC there was a Windows version of Python for a while that had built-in
support for COM interop in both directions - you could define IDispatch-based
COM objects in Python and implement interfaces while consuming COM libraries
using their typelibs.

~~~
badsectoracula
I wouldn't call it successful, COM is mainly used by Microsoft and pretty much
nobody else uses it unless they want to interface with Microsoft's products
(Office, etc).

In any case, yes, this is what i meant with the dynamic part. But the comment
i replied to wrote that it made "possible to write applications on Windows and
integrate with pretty much anything in it in any language with COM bindings",
which - as i wrote - doesn't need COM.

------
m-hilgendorf
While we've been hacking on the vst3-sys crate [0], we wound up forking the
mentioned com-rs crate to support COM APIs on non-win32 targets (notably,
there's some stuff with endianness of the IIDs, the calling convention of the
generated vtables) as well as usability (the com-rs crate only supports up to
5 interfaces implemented at once). We're still chasing down some issues with
order mattering when implementing the interfaces. Even without those small
changes, it's an impressive piece of macro programming that is very close to
being usable for general purpose, ABI-stable rust crates.

As a little dose of irony, clippy doesn't like the com-rs crate too much.

[0]
[https://github.com/RustAudio/vst3-sys.git](https://github.com/RustAudio/vst3-sys.git)

------
weiming
Now I'd like some native Rust bindings for Cocoa/UIKit, perhaps as an
"official"/higher-level alternative to
[https://crates.io/crates/objc](https://crates.io/crates/objc). There are some
crates already attempting to replicate all of Apple frameworks, but they are
community-supported/require a bit of `unsafe`.

~~~
Klonoar
You won't get around the unsafe.

I've been hacking away at these for a few months now:
[https://github.com/ryanmcgrath/cacao](https://github.com/ryanmcgrath/cacao)

Goal is to get a good-enough version to build apps with. I'm dogfooding it for
my next product so there's some incentive to keep pushing.

------
alkonaut
Never really understood whether WinRT binds me to store apps, sandboxes, appx
and so on.

Can I develop a single windows app with this that runs on Windows 10 desktop
as a win32 app does (such as a plugin to another application where I can’t
can’t decide the deployment model)?

~~~
contextfree
WinRT, as in the API/ABI shape, at this point really isn't tied to any aspect
of the UWP app model (other than that existing UWP-related APIs tend to be
newer and more likely to use it). Third-party WinRT component activation used
to depend on app packaging but that dependency was removed last year:
[https://blogs.windows.com/windowsdeveloper/2019/04/30/enhanc...](https://blogs.windows.com/windowsdeveloper/2019/04/30/enhancing-
non-packaged-desktop-apps-using-windows-runtime-components/)

In general what used to be various facets of the "monolithic" Win32 vs. UWP
divide have been refactored to allow a la carte usage, so not only can you
activate your WinRT components without a packaged app, but you can also
register your app as "packaged" for runtime purposes without having to install
in that format (
[https://blogs.windows.com/windowsdeveloper/2019/10/29/identi...](https://blogs.windows.com/windowsdeveloper/2019/10/29/identity-
registration-and-activation-of-non-packaged-win32-apps/) ), can install in the
packaged format without having to use the sandbox features (
[https://docs.microsoft.com/en-
us/windows/msix/overview](https://docs.microsoft.com/en-
us/windows/msix/overview) ) can distribute sandboxed apps outside the store (
[https://docs.microsoft.com/en-us/windows/msix/app-
installer/...](https://docs.microsoft.com/en-us/windows/msix/app-
installer/app-installer-root) ), etc.

The only remaining aspect I'm aware of where there's still a binary decision
and coupling is in the windowing model and shell integration; a Win32
process's top-level windows can only be HWNDs and a UWP process's top-level
windows can only be CoreWindows. Win32 HWNDs can host both Win32 and UWP UI,
but UWP CoreWindows can only host UWP UI; on the other hand, only UWP
CoreWindows can make use of UWP shell integration features like fullscreen and
picture-in-picture. It would make sense to somehow decouple this facet as well
but I'm not aware of any plans to do so.

~~~
alkonaut
Thanks this is informative. I think my confusion comes from that many things
are introduced as walled-off vertical concepts but later backported at least
partially. Also there is no lack of terminology confusion when things can be
an API, an app-model or both.

I’m a full time windows desktop dev since 15 years now. And I still find these
UI and app model frameworks extremely confusing (which is why I haven’t gone
near one after WPF).

~~~
contextfree
Yeah, it's definitely confusing for anyone who hasn't been following all the
twists and turns (i.e., the vast majority of developers)

------
wicket
Well this really confused me as I thought Microsoft had discontinued the
Windows RT operating system. It turns out that they also have a platform-
agnostic application architecture, ingeniously named WinRT.

------
optimiz3
Coding in C++/WinRT (similaly, C++/CX) is in my experience a major mistake
when targeting WinRT/UWP using C++. The primary use case for WinRT/UWP is
making apps for the Microsoft Store, where most of the time you're going to be
sharing code also targeting Google Play and the Apple Store given those
markets are vastly larger (and have viable ad-platforms; Microsoft is shutting
theirs down on June 1st).

The C++/WinRT and C++/CX language projections are incompatible with compilers
that target Android and IOS due to WinRT reference specific syntax and
keywords such as the '^' reference indicator.

As an alternative, it is possible to access all of the same WinRT/UWP platform
functionality in pure C++ without the C++/WinRT syntactic sugar extensions,
allowing you to cleanly abstract the WinRT/UWP platform APIs relative to
Android and IOS. This is not well documented but by far a superior option for
folks familiar with COM and Windows internals.

Furthermore, avoiding things like '^' reference operator syntax gives you
tighter control over object lifetime as C++/WinRT and C++/CX hide to some
degree the mechanics of COM object lifetime and gives a pseudo-environment
much more like C# on .Net.

Microsoft does provide the WRL pure C++ template library, which is in many
ways a spiritual successor to the ATL COM template library. WRL is in my
experience the best way to interact with COM objects surrounding WinRT and
UWP.

(Source: developer of several top 10 apps (at times) on Microsoft Store).

Glossary of Microsoft terms:

WinRT/UWP (WinRT (Windows Runtime) the old name used in Windows 8/8.1 for what
later was renamed to UWP (Universal Windows Platform) in Windows 10).
WinRT/UWP was originally intended to be an object-oriented replacement API for
Win32 but hasn't lived up to its charter due to only being useful for
Microsoft Store apps and being significantly less capable than Win32.

COM - Component Object Model; an object-oriented API style used by some Win32
APIs, this style was used near-exclusively as the basis for the WinRT APIs.
COM can be unweildy to deal with so there are several C++ template libraries
like WRL and ATL to make it easier.

C++/WinRT (and C++/CX) are Microsoft specific C++ extensions that require MSVC
and hide the complexity of dealing with COM relative to WinRT/UWP APIs.

~~~
hyperrail
C++/WinRT and C++/CX are not the same; they are different enough that
Microsoft Docs has a whole page explaining how to move from C++/CX to
C++/WinRT: [https://docs.microsoft.com/en-us/windows/uwp/cpp-and-
winrt-a...](https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-
apis/move-to-winrt-from-cx)

In particular only the older C++/CX has ^ pointers or other Microsoft-specific
C++ language extensions. C++/WinRT is standard C++.

Writing your code using WRL (Windows Runtime C++ template Library) is good if
you want to learn enough about how the Windows Runtime extensions to COM work
in order to debug effectively. However, its close relationship to the
underlying COM and Windows Runtime APIs also makes it far too verbose to
quickly write good API-consuming and -producing code, in my opinion.

~~~
optimiz3
Updated my post - I had forgotten C++/WinRT discarded the ^ syntax as we
skipped C++/WinRT for our development as it suffers from many of the same
problems of C++/CX.

~~~
favorited
> it suffers from many of the same problems of C++/CX

The whole point of C++/WinRT is to be 100% standards-compliant C++. The guy
who created it didn't even work at Microsoft at the time.

~~~
zeroc8
And now he created the Rust bindings.

------
znpy
I want to reply to many other comments but I want to make this more visible:
Microsoft does not do Embrace-Extend-Extinguish anymore today (or at least, it
does a lot lot less).

You know who does Embrace-Extend-Extinguish? Google.

------
mwcampbell
Looks like async/await support isn't ready yet. I wonder how challenging it
will be to integrate WinRT's async model with Rust's futures and tasks.

~~~
ComputerGuru
IAsyncOperation is pretty flexible. I don’t think it will be technically hard,
though perhaps picking the best fit model will be a time consuming process.

------
dstaley
I'm super excited for this! I do wish that they'd ressurect their JavaScript
projection for the runtime though. Especially with their focus on React
Native, it'd be awesome not to need a "native" module to call Windows APIs.
That being said, I also hope Rust/WinRT becomes a valid native module format
for React Native (though I suspect it won't since that would likely require
React Native developers to have the Rust toolchain setup to compile the
module).

~~~
Kipters
Something like this already exists:
[https://github.com/NodeRT/NodeRT](https://github.com/NodeRT/NodeRT)

~~~
dstaley
This is neither an official language projection nor for React Native.

~~~
Kipters
It's not official, but it was endorsed by MSFT on stage at last build. You're
right about RN, I did not realize that.

------
cs702
You have to hand it to Microsoft: It may be the only large software company
that doesn't seem susceptible to not-invented-here syndrome.

It's true that Microsoft historically has been an intensely competitive
company, often trying to undermine competing technologies, e.g., with "embrace
and extend" strategies.

But whenever a competing technology -- whether a language, or a framework, or
an application -- _gains adoption_ with developers or users, Microsoft to its
credit will follow along, sooner or later, and do the work necessary for
making it a first-class citizen on Windows.

(For those who don't know, Rust is originally a Mozilla project.)

~~~
tambourine_man
It’s always easy to be an open source proponent when you are the underdog.

And Microsoft, as crazy as it sounds to me, kinda is when it comes to cool dev
stuff.

We'll have to see if they have really changed or just waiting to regain ground
and going back to the extinguish part.

But what I can confidently say is that, of all the BigCorps, Microsoft is the
only one actively trying to make developer's life easier.

Apple is consumer first, so MacOS is getting harder and harder to hack on, for
better and worse.

Chromebook was never a serious competitor. And Linux is Linux, hackable to a
fault.

But Windows… which I have always despised, is, for the first time in my life,
tantalizing… to some extent.

~~~
cheez
The Microsoft you remember is at a time when dev tools were "the future". They
are now the past. Microsoft's ruthlessness is no doubt focused elsewhere now.
For example, do they go out of their way to make your code portable b/w Azure
and Google? Probably not.

~~~
CodeM0nkey
Off the top of my head here are three different offerings from Microsoft that
enable cross cloud applications: \- [https://azure.microsoft.com/en-
us/services/azure-arc/](https://azure.microsoft.com/en-us/services/azure-arc/)
\- [https://dapr.io/](https://dapr.io/) \-
[https://keda.sh/](https://keda.sh/)

~~~
Kipters
The runtime for their serverless functions is also open source and (I guess)
fairly portable: [https://github.com/Azure/azure-functions-
host](https://github.com/Azure/azure-functions-host)

------
jhoechtl
Would this be possible for Go too?

~~~
favorited
It is possible for any language, really. They already have 3 language
projections for C++ (C++/WinRT being the newest, by the same person running
this Rust projection), C#, VB, and JavaScript.

Under the hood they call out to (and potentially expose) COM interfaces which
are C. So if your language has C interop, or if it could be added, something
like this could be built.

~~~
camccar
C interop is slow in golang so I don’t think it would be the best language for
it. People do it with SDL though

------
boromi
Sorry for the naive question, but how does this fit into WinUI 3.0?

~~~
camccar
Yes

------
ridiculous_fish
How does this projection work with the borrow checker? UI frameworks typically
allow you to have multiple mutable reference to the same element.

~~~
Rusky
It works fine- Rust only forbids multiple `&mut T`s to the same object, but
`&mut T` doesn't exist outside of Rust, so code in other languages doesn't
have to care about that rule at all.

These bindings can just expose non-Rust pointers as (wrapped) raw pointers,
leaving all the actual dereferencing and mutation to the other language. WinRT
objects don't expose anything but virtual methods on opaque objects anyway, so
this isn't even Rust-specific.

Outside of WinRT this sort of thing requires a bit more thought, but you can
still use the usual tools- `Rc` and `Cell` or their variants, or raw pointers
and `unsafe`.

You can think of `&T` and `&mut T`, and their associated "no shared
mutability" rule, as a compiler-checked version of C's `restrict`. Stop using
`restrict` and the rules go away.

~~~
ridiculous_fish
Is the projection literally "wrapped raw pointers?" How are the raw pointers
wrapped - for example is there interop between COM reference counting and Rust
Arc? Or something else?

Here's a classic trap: you get a reference to something interior, and then the
parent is deallocated. My event handler gets a ref to this button's label and
then replaces the button. Is this possible with Rust/WinRT? (No judgement
either way!)

~~~
pornel
Rust's borrow checker solves the problem of "get a reference to something
interior, and the parent is deallocated". It knows (by static analysis) when
an inner reference may be in use, and won't let the program compile if the
parent could deallocate during that time.

This works well even with externally refcounted objects. You can give
reference to an inner object without increasing its refcount, and rely on the
borrow checker not to allow the parent to decrease the refcount. Or you bump
the refcount of the inner object and give it out as an independently owned
object.

~~~
ridiculous_fish
WinRT is lousy with functions like Window.Current which provide global access
to the current window. Any function may get access to any control at any time.

------
zeroc8
As a former MFC/Winforms/WPF/Qt now turned Angular developer, this is really
sparking my interest. I would love to back to writing great desktop
applications. Problem is, most of my projects nowadays require a multiplatform
GUI. Desktop is not enough, we also need web and mobile.

------
brian_herman__
This is so cool. I should brush up on my rust maybe I should make a python
extension or something...

------
adzm
With Windows 7 on its way out slowly, WinRT is becoming more palatable.

~~~
loeg
Slowly?! Hasn't Win7 been dead for years?

> Latest release Service Pack 1 (6.1.7601) / February 22, 2011; 9 years ago

> Mainstream support for Windows 7 ended on January 13, 2015.

There is:

> Extended support for Windows 7 ended on January 14, 2020.

But that is referring to very specific business contracts, not casual users
pretending EOL never happened.

~~~
badsectoracula
> Slowly?! Hasn't Win7 been dead for years?

No. Microsoft wants to kill it, but... even just checking Steam's hardware
survey (users of which are more likely to upgrade so chances are overall PC
usage of Win7 is higher) there is a combined ~7% of users on Win7.

With ~25M concurrent users the last 48 hours, that means there were more than
1.7M users running on Win7 just within the last two days.

FWIW these numbers are a bit lower than 10 times the Linux numbers of all
distros combined.

------
Ericson2314
[https://github.com/retep998/winapi-rs](https://github.com/retep998/winapi-rs)
they should work with this

~~~
steveklabnik
These are two different APIs, so it's not clear to me how they would.

~~~
Ericson2314
I thought there was much overlap

~~~
steveklabnik
My understanding is that there’s a lot of overlap but also stuff that only one
or the other can do.

~~~
Ericson2314
Would `#[cfg(..)]` be the right way to do this then?

------
xrd
I stopped reading at "The Windows Runtime is based on Component Object Model
(COM) APIs..."

Is that a bad choice on my part?

I see COM and think of OLE, CORBA and I remember that I'm old and going to die
pretty soon (within the next 40-50 years almost assuredly).

[https://en.wikipedia.org/wiki/Component_Object_Model](https://en.wikipedia.org/wiki/Component_Object_Model)

~~~
pjmlp
Yes it is.

After the whole political disaster that was Longhorn, the Windows team decided
to rebuilt Longhorn ideas, originally based on .NET, and redo them with COM.

So while many outside Windows have considered COM dead, actually since Vista
all major Windows APIs have been provided as COM interfaces, the large
majority of Win32 surface has been frozen since Windows XP.

With WinRT/UA/UAP/UWP they have gone back to the roots, while pursuing this
idea one level up.

Basically they replaced COM type libraries with .NET Metadata, added support
for generics, structured data types and implementation inheritance, bringing
it to what .NET would have been like if they did not decided to copy Java.

So while the implementation of this reboot has been somewhat clusmy, COM is
not going anywhere on Windows.

Also, this isn't a Windows only thing, Linux has gathered around DCOP, Android
has AIDL, Fuchsia FIDL, macOS/iOS has XPC, then there is gRPC and plenty of
other variants.

~~~
amaranth
I think the most similar thing to WinRT on Linux would be GObject
Introspection since the main point appears to be a way to somewhat
automatically surface the platform API in multiple languages using language-
specific idioms. D-Bus is instead for RPC and events, which I guess COM also
gets used for?

~~~
pjmlp
I guess you are kind of right, then it would be a mix of GObject, KParts and
D-BUS then.

As for COM, yes there are multiple models, in-process, external process and
across the network (with DCOM).

GObject and KParts would be the in-process variant, with D-BUS for the other
execution models.

------
jimbob45
Wish they'd open the source and let the Rust community do this kind of stuff
instead. No need to waste Windows development time on niche stuff.

~~~
snuxoll
Open what source? Everyone has access to the winmd files necessary, the COM
ABI is documented - there’s been nothing stopping anyone from doing this.

All of the work MS has done on these bindings is MIT licensed as well.

~~~
contextfree
In fact there were third-party bindings already which I worked on:
[https://github.com/contextfree/winrt-
rust](https://github.com/contextfree/winrt-rust)

the new first-party ones look to be more complete and polished but this is
mainly due to time and skill limitations on my part. :)

