
Designing a COM Library for Rust - arunc
https://msrc-blog.microsoft.com/2019/10/08/designing-a-com-library-for-rust/
======
holy_city
This is similar to the work done in winapi [1], com-imp[2] and my own
tangential work on porting VST3 [3] to Rust [4]

I'm really glad MS is doing this. What needs to be a bit clearer to me is how
they maintain ABI compatibility under the hood of MSVC for COM interfaces
(which uses the vtable layout of an inherited class) and how that's compatible
with MinGW/GCC stacks on Windows, mostly what can break it. I got stuck
porting VST3 with multiple inheritance, and it was a headache trying to
reverse engineer the appropriate struct layouts for COM implementations.

[1] [https://github.com/retep998/winapi-
rs/blob/0.3/src/macros.rs](https://github.com/retep998/winapi-
rs/blob/0.3/src/macros.rs)

[2] [https://github.com/Connicpu/com-impl](https://github.com/Connicpu/com-
impl)

[3]
[https://github.com/steinbergmedia/vst3sdk](https://github.com/steinbergmedia/vst3sdk)

[4] [https://github.com/m-hilgendorf/cli-
host](https://github.com/m-hilgendorf/cli-host) (sorry for the messy code, it
was a weekend of hacking away trying to host a VST3 in pure Rust)

~~~
barrkel
COM is an ABI standard. The structs are defined in terms of C with Winapi
(stdcall) calling convention. Very little needs reverse engineering - it's all
pIntf->vTable->func(pIntf, ...). You can explain it on a whiteboard in a
couple of minutes.

The way MSVC does it may need reverse engineering (it may be patented btw). I
could explain how Delphi implements COM interfaces, but any specific
implementation is actually more complicated than the ABI, because they're
trying to add implementation ergonomics on top of the basic calling
convention.

~~~
holy_city
Is the ABI documented anywhere? Every time I google around for it, I just get
information like "COM is ABI stable and language agnostic" but not _what_ the
ABI is. I've successfully implemented implementations of single COM interfaces
and get the basics, my trouble was in implementing many interfaces for the
same implementation and running into copious segfaults when testing the Rust
implementation through a reference app written in C++.

~~~
pjmlp
Here are some good COM books.

Essential COM by Don Box

[https://www.amazon.com/Essential-COM-Don-
Box/dp/0201634465](https://www.amazon.com/Essential-COM-Don-Box/dp/0201634465)

Inside COM by Dale Rogerson

[https://www.amazon.com/Inside-Microsoft-Programming-Dale-
Rog...](https://www.amazon.com/Inside-Microsoft-Programming-Dale-
Rogerson/dp/1572313498)

Then if you have access to public libraries, maybe one of them has one of the
several Microsoft Systems Journals issues, later MSDN Magazine, with plenty of
low level COM articles.

COM is from the days where good documentation was to be found in books, not on
the Interwebs.

~~~
teh_klev
+1 for Essential COM by Don Box, it still survives my bookshelf
purges..."just-in-case". IUnknown and IDispatch are burned permanently in my
memory from a period of my life building a COM/CORBA bridge.

~~~
alxlaz
I'm gonna piggyback on your comment to give another shout out to Essential
COM. I haven't touched COM in ages but that book is so good I still pick it up
every once in a while -- and it was a lifesaver back when I _did_ touch COM on
a daily basis.

------
Crinus
Weirdly, the github page says:

> COM has been superseded by WinRT which builds on COM to provide even more
> guarantees about the binary interface.

Yet the WinRT page says:

> The Windows Runtime is based on Component Object Model (COM) APIs, and it's
> designed to be accessed through language projections. A projection hides the
> COM details, and provides a more natural programming experience for a given
> language.

Which implies that WinRT doesn't supersed (ie. replace) COM but it uses COM
itself (though the "language projection" part makes me think that the way it
is used is so convoluted that you need language extensions to make it
tolerable :-P).

~~~
pjmlp
WinRT is an evolution of COM.

Basically there is a new base interface, IInspectable instead of IUnknown, and
many more datatypes are allowed to cross the wire between processes, making it
easier to also use generics, lists and arrays across COM libraries.

Additonally, .NET metadata libraries are using instead of the old COM type
libraries.

If you prefer, it is the original design of .NET before the CLR came into
play, and related to the Longhorn architecture, just using COM instead of
.NET. A path started in Vista.

Now for this Rust approach to win the hearts of Windows devs, it needs to be
as productive as C++/CX or C++/WinRT VS tooling, in all COM/UWP usage
scenarios.

~~~
Crinus
One thing i'm not sure about WinRT and cannot figure out from the docs, AFAIK
it is possible to "bit bang" (or "byte bang" if you will) a COM object by
arranging everything in memory using plain old C structs (or equivalent for
other languages) from compilers that weren't COM aware. Is it possible to do
the same with WinRT or it requires the language to be WinRT aware? F.e. could
i get something like TCC and write some code that uses a WinRT object even
though TCC has no idea about WinRT?

~~~
pjmlp
Not really, as it is more elaborated.

[https://docs.microsoft.com/en-us/uwp/winrt-cref/winrt-
type-s...](https://docs.microsoft.com/en-us/uwp/winrt-cref/winrt-type-system)

The documentation is a bit lacking, as it appeared with WinRT, then we had
UAP, and finally UWP. While it all boils down to the same, those marketing
changes, did cause the documentation to keep changing.

Alongside C++/CX, there was the low level "Windows Runtime C++ Template
Library (WRL)", which was basically an evolution of ATL, with MDIL 2.0.

[https://docs.microsoft.com/en-us/cpp/cppcx/wrl/windows-
runti...](https://docs.microsoft.com/en-us/cpp/cppcx/wrl/windows-runtime-cpp-
template-library-wrl?view=vs-2015)

Eventually MIDL improved to 3.0, as the work on C++/WinRT progressed.

[https://docs.microsoft.com/en-us/uwp/midl-3/](https://docs.microsoft.com/en-
us/uwp/midl-3/)

[https://channel9.msdn.com/Shows/ifdefWINDOWS/MIDL3-with-
Larr...](https://channel9.msdn.com/Shows/ifdefWINDOWS/MIDL3-with-Larry-
Osterman)

Here are some technical documents and sessions related to WinRT.

 _" The Windows Runtime"_

[https://channel9.msdn.com/Events/Lang-NEXT/Lang-
NEXT-2012/Th...](https://channel9.msdn.com/Events/Lang-NEXT/Lang-
NEXT-2012/The-Windows-Runtime)

 _" Windows Runtime internals: understanding "Hello World""_

[https://channel9.msdn.com/events/Build/BUILD2011/PLAT-875T](https://channel9.msdn.com/events/Build/BUILD2011/PLAT-875T)

The C++/WinRT talks from Kenny Kerr, related how they migrated from C++/CX
language extensions to the C++17 compliant WinRT in chronological order.

 _" CppCon 2017: Scott Jones & Kenny Kerr “C++/WinRT and the Future of C++ on
Windows”"_

[https://www.youtube.com/watch?v=7TdpWB_vRZM](https://www.youtube.com/watch?v=7TdpWB_vRZM)

 _" Effective C++/WinRT for UWP and Win32"_

[https://www.youtube.com/watch?v=nOFNc2uTmGs](https://www.youtube.com/watch?v=nOFNc2uTmGs)

 _" Meet C++/WinRT 2.0: Faster and smarter in the open"_

[https://www.youtube.com/watch?v=X41j_gzSwOY](https://www.youtube.com/watch?v=X41j_gzSwOY)

Uff, hope this sheds some light on your questions and anyone else that wants
to get a clearer picture of COM and its evolution into UWP.

~~~
ak39
This reply should go into HN hall of fame.

Thank you very much!

------
thrower123
COM interop used to be a big buzzword say, a decade ago, but I haven't really
heard or seen much usage of it since.

Most of my experience in using it has been horribly abusing it to drive Office
applications and Notes to do some awful things because at the time there
weren't any libraries to manipulate certain file types. I have done some truly
heinous things with the Lync/Skype COM-based client SDK, back in the times
when the Office 365 version of that product was viable, and there was no other
API options available.

~~~
emddudley
> I haven't really heard or seen much usage of it since.

I think COM is incomprehensible to most developers today--it certainly is to
me, and I maintained a .NET application with COM components for several years!
COM is so arcane and verbose.

Why invest hundreds of hours learning something with no clear benefit or
future? The documentation introduces COM as:

[https://docs.microsoft.com/en-
us/windows/win32/com/component...](https://docs.microsoft.com/en-
us/windows/win32/com/component-object-model--com--portal)

> COM is a platform-independent, distributed, object-oriented system for
> creating binary software components that can interact. COM is the foundation
> technology for Microsoft's OLE (compound documents) and ActiveX (Internet-
> enabled components) technologies.

What does that even mean? It sounds obsolete.

~~~
ralphc
When I read the headline it was a mix of WHYYYYYYYY and NOOOOOOO

Really, can't we just leave COM in the 90's?

~~~
pjmlp
Win32 is the one left in the 90's.

COM gets regularly new APIs.

------
ajxs
I'm interested in more information regarding the Safe Systems Programming
Languages team's work. Did they assess other languages other than Rust? I'm
scanning through their blog entries, without having read every single one in
depth so please pardon me if I miss something, and I'm not seeing anything
mentioning formal methods or other systems programming languages. It's a very
interesting development for sure!

------
jchw
Very cool.

I have played with COM in Go to a lesser extent. It’s not too bad actually. My
intent was to write Go wrappers around all of the TSF COM interfaces, but I
burnt out after getting basic IME working - TSF is enormous!

~~~
MehdiHK
Hi,

I believe you are talking about this repo [https://github.com/jchv/go-
tsf](https://github.com/jchv/go-tsf)

Do you know any other project that's working on creating basic IME on top of
TSF in Go?

~~~
jchw
You are correct, and no I am not. Is your goal to build an application with
IME support, or an entire IME?

~~~
MehdiHK
An entire IME.

~~~
jchw
Ah I see.. sadly, I never really figured out a great way to support full COM
interop in Go. It would be ideal if you could implement an interface and
register it as a COM object, but I hadn’t hashed out exactly how.

