Visual C++ and WinRT/Metro - Some fundamentals

The fundamentals of using Visual C++ to consume and create WinRT objects

Developer Preview Warning

This article and its contents are based on the first public developer
preview of Windows 8 and Visual Studio 11. The code snippets and other
information mentioned in the article may thus be subject to significant changes
when the OS/VS hits beta/RTM.

Targeting WinRT/Metro

WinRT is the new API for writing Metro applications on Windows 8. Unlike
traditional Windows APIs, which were C based, WinRT is a COM based C++ API. COM
itself has been significantly improved and enhanced to support modern object
oriented design paradigms. So you now have concepts like inheritance and static
functions (which might appear amusing to traditional COM developers). The big
advantage here has been that this allowed the developer division to bring out
true language parity when it came to releasing compilers for the various
Microsoft languages (Visual C++, C#, VB and now JS/HTML5). They achieved this
through the use of language specific projections where the underlying WinRT
objects are projected into language structures that are semantically
familiar to developers of specific programming languages. I don't really want to
talk about the WinRT programming model here, instead in this article I intend to
quickly go through the fundamentals of using Visual C++ to consume and create
WinRT objects.

Why use C++?

After years of enduring developer frameworks such as Windows Forms, WPF
(Avalon), and recently Silverlight that were clearly meant to be consumed from
C# and VB, and which required a C++ consumer to jump through some serious hoops
to have a shot at using them, this is a very valid question. Well here's the
gist of it. WinRT is native. I'll repeat that once more, this time with an
exclamation. WinRT is native! While the COM based design has made it palatable
for consumption by managed clients, you do incur the price of native-managed
interop when you do that. But then performance is often an overrated concept.
Why save 20 nanoseconds when the database/web-service call will take 2 seconds
anyway? Well, not all apps work that way. There are a substantial number of apps
where even a minor improvement in performance can mean a lot to the end-user.
And the way C++ has evolved, we've reached a point where we don't really have to
be masochists to get better performance. It's naive to pretend that using C++
will be as easy as using C# or VB. But it's equally naive to remain ignorant of
modem changes that the language and its libraries have gone through that makes
it a lot less complicated to use than say 5 years ago. If you are a C++
developer, would you be willing to put in say 15-20% more effort to get 15-30%
more performance? The answer to that question is the rationale for this article.

C++ Component Extensions

Now while WinRT itself was developed partially in C++, it was not designed for direct consumption from C++
callers. It had to support other languages too, and thus the COM based API. Now
when I say COM, I am not being accurate because WinRT is a lot more than COM,
but I'll continue to use the word COM here for lack of a better alternative, and
saying RT in lieu of COM sounds garish. Visual C++ 11 introduces a new
programming model / syntax for creating and consuming WinRT components. They
call it the C++ Component Extensions or C++/CX for short. Syntactically, it's
nearly identical (not 100% though) to the C++/CLI syntax that is used to target
the CLR. So if you've used C++/CLI before (or happened to write a book on it
like this guy I know of), you'll find the syntax really familiar. It's a little
like an alien spaceship landing on earth and then we find that the aliens speak
English but with a Welsh accent. The accent is weird for sure, but it's still
English of sorts.

Well the similarity is purely syntactical though, the semantic meanings and
implications are entirely different. C++/CX is native code, C++/CLI is managed
code. C++/CX allows the developer to focus on the important things, like
designing his code and data structures instead of wasting time getting the COM
calls right. One of the reasons COM struggled to remain popular once .NET was
out was that when doing serious COM, you end up spending way too much time doing
plumbing work instead of focusing on your actual application.

ref new and ^ (hat)

C++/CLI had the gcnew keyword added to it which was the CLR
equivalent of the native new. Similarly C++/CX has the contextual
ref new keyword to create WinRT objects. ref new
returns a ^ (hat) which is similar to a * (pointer)
except that it is used with ref-counted COM objects. Here's a code example.

Notice the call to ref new (as opposed to new) and
how the returned variable is of type ^ (and not *). I
used that syntax to show how the returned type is a hat, normally I'd just have
used auto.

auto comp = refnew WinRTComponentDll2::WinRTComponent();

Or I could have totally avoided ref new and used
stack semantics.

WinRTComponentDll2::WinRTComponent comp;

So if you have an aversion to seeing the hat all over your code, you can
avoid seeing it in some places. You do need to keep in mind that you are not
merely creating a C++ object in the heap. The comp object we
created is a COM object. Under WinRT, COM objects are created via an activation
factory. An activation factory implements the IActivationFactory
interface.

WinRT includes a RoGetActivationFactory function that gives you
the activation factory for a specific WinRT class. If you implement your own
WinRT class, then you need to implement a factory as well (that implements

IActivationFactory

). That said, you don't really need to do that because
the compiler will generate that for you when you use C++/CX. So once the

IActivationFactory

object is obtained, the ActivateInstance
method is called on it. If the call is successful, a pointer to a

IInspectable

object is returned (via the out parameter).

IInspectable

is to WinRT what IUnknown was to traditional
COM. IInspectable inherits from IUnknown, so this is
what makes every WinRT component a COM object as well in a manner of speaking.

. Once we have the IInspectable object, getting
the interface we want is a mere matter of calling QueryInterface.
The compiler also generates code to call AddRef and Release
as appropriate. So when you do something that's seemingly quite trivial (calling
ref new), there's a good bit of stuff that goes on underneath which
is something to keep in mind from a performance perspective.

What's a hat?

Deon Brewis had a C++ session at //Build/ where he defined a hat as syntactic
sugar for a pointer to a vtable, or in other words a pointer to a pointer to
function pointers. Just to put that in better light, take a look at the
following code.

So, how do I know that the function pointer I need is the 5th in the vtable.
Well IUnknown has QI, AddRef, and

Release

- so that takes up the first 3 spots, then we have the

IInspectable

methods with GetIids at 4th spot, followed by
GetRuntimeClassName, and then GetTrustLevel. This is
fixed and will never change for any WinRT object.

Every time you invoke a method on a hat, it's a COM call on the appropriate
interface. Consider a simple method call such as the following.

comp->Method(5);

This will result in a QueryInterface call for the appropriate
interface. C++/CX will wrap all non-virtual methods defined in a custom WinRT
class into a compiler generated interface which in the dev preview shows up as
__IWinRTComponentPublicNonVirtuals in the winmd metadata file. So
every method call on a hat will be a virtual function call, something to keep in
mind.

Using Platform::String

In the earlier code example, you may have seen the use of an HSTRING.
An HSTRING is a handle to a WinRT string and seems to be the RT
equivalent of COM's BSTR. Strings are immutable in WinRT. There are
methods such as WindowsCreateString, WindowsDeleteString
etc. that can be used to manipulate HSTRINGs. You can also get the
raw buffer using WindowsGetStringRawBuffer. As you might imagine,
it's not convenient at all to be doing all this and quite unsurprisingly, the
C++ library includes a wrapper/helper class called Platform::String.
Here's a small code snippet that manipulates strings and shows the corresponding
WinRT calls that the wrapper makes for you.

Pretty much every operation with a String^ results in a WinRT
call. The compiler might optimize some of those calls away but in such scenarios
it's best to not always depend on the compiler to do that for you or to make
such assumptions. This is very important to be aware of. When designing custom
WinRT components, you should only ever use String^ at ABI
boundaries. For all internal code you absolutely must use C++ strings (like
std::wstring). And since you are C++ programmers, here's another
piece of advice. Never modify the raw backing buffer as WinRT will always assume
that the raw buffer is immutable and null-terminated.

Creating WinRT components

Consuming components is merely a matter of ref new and then
invoking methods on the hat. Creating custom components is just about as easy
too.

The syntax is eerily similar to C++/CLI (in my opinion, that is by design).
COM does not really have properties so getter and setter methods are generated.
In C++/CLI you could not mix types together, as in you could not embed a native
class in a managed class or a managed class in a native class without using
indirections like gcroot or CAutoNativePtr (which I
wrote). There are no such restrictions with C++/CX. You can mix C++ and RT
types.

When designing WinRT components, the one restriction you have is that you
must use only WinRT types in your public methods. You cannot use C++ types in
your public interface. Fortunately, the compiler won't let you do this
inadvertently.

Notice how the compiler doesn't care what you do with your private methods.
It's just the public methods that it cares about.

The Object class

All WinRT components derive directly or indirectly from Object.
The .NET paradigm where System::Object is the absolute base class
with overridable methods does not translate too well here. WinRT was not
designed with inheritance in mind and inheritance is officially supported only
for Xaml components. None of the methods in Object are virtual. So
you might see a ToString in Object and think that you
could override it to return something nice. Nope, won't work, can't do! If you
really wanted something similar, you may probably want to consider having your
own root-base class and then implementing your object hierarchy from there. The
way I think of the use of Object^ in C++/CX is like a

void*

(there is no such thing as a void^ by the way). My
strictly unofficial opinion here is that Object ending up as the
base class for all classes was a design decision to make it convenient for
managed languages like C# and VB to consume and create WinRT components.

Boxing

The VC++ team and boxing have a bit of a history. When they first released
Managed C++, they used __box as a keyword to perform explicit
boxing. This was when C# already had implicit boxing. Later, when C++/CLI was
first launched, one of the big changes was that boxing was now implicit. Well
with C++/CX, we now come back to explicit boxing. And it's not even that
straightforward at the moment.

By the time VC++ 11 RTMs, I suspect there will be more helpers/wrappers added
that will make most of these conversions a little easier. But either way, it's
not very complicated to do on your own.

Don't care for the component extensions?

A few C++ devs I talked to say that they cannot stand the C++/CX syntax and
that it's not really C++. Well you don't need to use the C++/CX syntax if you
don't want to. You can just directly use regular C++/COM to write WinRT
applications. You could think of C++/CX being high-level WinRT access and
regular COM as low-level access. But it's going to be a fairly large amount of
work to get that working. You'll have to do all the stuff that the compiler does
for you in high-level mode, such as creating the activation factory,
implementing IUnknown and IInspectable. Manually deal with
HSTRING. Make sure
you handle ref-counts correctly. The QueryInterface part of doing things will be
the least of your worries. And lastly, since COM does not really do inheritance
the C++ way, WinRT uses a form of composition to emulate inheritance. So
when you have multi-level object models, you'd end up writing even more code
just to get it all to compile and run. Outside of an academic exercise, it makes
no sense to subject any developer to those extremes.

There is an alternative though. It's called the Windows Runtime Library (or
WRL for short). At the moment there is very little (zero in fact) documentation
on MSDN (or anywhere else). It's basically the ATL equivalent for WinRT. WRL
seems to be owned by the SDK team rather than the VC++ team, and you'll find the
header files in this location (in the dev preview) :

Program Files
(x86)\Windows Kits\8.0\Include\winrt\wrl

. I'd guess that at least parts
of WinRT was developed using WRL, so it should be fairly bug-free by the time it
RTMs. So if you absolutely want to avoid C++/CX then WRL should be your best
option (straight COM most certainly would be an utter impracticality).

Conclusion

These are exciting times if you are a C++ programmer or if you were one in
the past and moved to C# or VB to better consume modern frameworks like WPF and
Silverlight. Because now, C++ is once again the first choice language for
writing Windows apps (at least Windows Metro apps). I am not saying there is no
reason to use C# or VB. For quick app development and for better IDE support,
those languages probably have an edge, specially when you add in all the
benefits of .NET and the vast Base Class Library. But for faster applications
with smaller memory footprints where performance is the key focal point, using
C++ to write Metro apps is the way to go because when you do that it's metal on
metal! The renaissance is here, finally.

History

September 29, 2011 - Article first published

License

Share

About the Author

Nish Nishant is the Principal Software Architect/Consultant for Ganymede Software Solutions LLC, and is based out of Columbus, Ohio. He has over 17 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish was a Microsoft Visual C++ MVP between 2002 and 2015.

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored C++/CLI in Action for Manning Publications in 2005, and had previously co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : If you are interested in hiring Nish as a consultant, you can reach him via his google email id voidnish.

Comments and Discussions

Once again an insteresting article from you.
It was exactly what I was looking for.

However you could give more details.
For example: What does "ABI" stand for ?

And you are talking about HSTRING:
> As you might imagine, it's not convenient at all to be doing all this and quite unsurprisingly,

I wrote a tiny class that wraps WindowsCreateString, WindowsDeleteString etc.
It is very easy to do that even in Visual Studio 2005 without using any hat (^) or ref new stuff! And yes: You can easily use WindowsRT in Visual Studio 2005!

You could post a tiny class for all those who are new to WindowsRT to show how easy it is to use HSTRING's.

Some more code examples would be nice.
An example how to call RoGetActivationFactory and RoActivateInstance and the corresponding LoadLibrary and GetProcAddress would be very helpfull.

Nish, your article was very informative. I am new to WinRT and Metro. I noticed that you state that WinRT classes cannot have public functions which take non WinRT classes (a fact that I had already discovered). Why is that?

I have the need to handle Metro events via a non WinRT class. I tried to create a WinRT handler class to handle the event and pass in a pointer to a non WinRT class that would be called when the event occurred, but, of course, this does not work. Is there some way to work around this restriction?

Thanks.

-------------------

Ok, it all makes sense to me now. For anyone else who is interested, the reason you cannot have WinRT Objects with public functions that have native C++ arguments is that these objects would then not be consumable by non C++ code. However, the (obvious?) solution is to make the constructor private and have the class that creates the Object declared as a 'friend' class (duh!). Then all is well, the compiler is happy, and I am happy.

I have Existing C/C++ Code(Static Lib) for an application which Uses Win32 And Direct X.
I wanted to Port it to WinRT for Metro App.
So Obviously I Need to Create Custom Classes(c++) in WinRT .As you said WinRT is COM Component,

So Will WinRT Custom Classes can be used in XAML or any Other Language.

If I want to convert a traditional MFT effect of windows 7 to metro style, how could I do?? I know the interface IInspectable is essential. But when I want to plug in the effect to the pipeline, how could I mix the original interface IMFTransform and IInspectable together to make it work. Do I need to activate the IMFTransform through the runtimeclass or is there another way to connect the effect to the source?? I can't figure out how the topology created. Are there any reference for studying??

Nice article. I have been following this with some interest. This gives COM programming a big lift from days of old. - Do you think it will be possible to access the WinRT from with Win32 space?

Now that we can create modern C++ apps that do not have to rely on the tierd and old MFC and instead use XAML & Expression Blend it would be a shame if traditional line of business apps were locked out becuase they are not running directly on Metro.