C++/CX Part 0 of [n]: An Introduction

C++/CX Part 0 of [n]: An Introduction

Rate This
  • Comments 65

Hello; I'm James McNellis, and I've recently joined the Visual C++ team as a libraries developer. My first encounter with the C++/CX language extensions was early last year, while implementing some code generation features for the Visual Studio 2012 XAML designer. I started off by hunting for some example code, and it suffices to say that I was a bit surprised with what I first saw. My initial reaction was along the lines of:

"What the heck are these hats doing in this C++ code?"

Actually, I was quite worried; because I thought it was C++/CLI—managed code. Not that managed code is bad, per se, but I'm a C++ programmer, and I had been promised native code.

Thankfully, my initial impression was uninformed and wrong: while C++/CX is syntactically similar to C++/CLI and thus looks almost the same in many ways, it is semantically quite different. C++/CX code is native code, no CLR required. Programming in C++/CLI can be very challenging, as one must deftly juggle two very different object models at the same time: the C++ object model with its deterministic object lifetimes, and the garbage-collected CLI object model. C++/CX is much simpler to work with, because the Windows Runtime, which is based on COM, maps very well to the C++ programming language.

Windows Runtime defines a relatively simple, low-level Application Binary Interface (ABI), and mandates that components define their types using a common metadata format. C++/CX is not strictly required to write a native Windows Runtime component: it is quite possible to write Windows Runtime components using C++ without using the C++/CX language extensions, and Visual C++ 2012 includes a library, the Windows Runtime C++ Template Library (WRL), to help make this easier. Many of the Windows Runtime components that ship as part of Windows (in the Windows namespace) are written using WRL. There's no magic in C++/CX: it just makes writing Windows Runtime components in C++ much, much simpler and helps to cut the amount of repetitive and verbose code that you would have to write when using a library-based solution like WRL.

The intent of this series of articles is to discuss the Windows Runtime ABI and to explain what really happens under the hood when you use the C++/CX language constructs, by demonstrating equivalent Windows Runtime components written in C++ both with and without C++/CX, and by showing how the C++ compiler actually transforms C++/CX code for compilation.

Recommended Resources

There are already quite a few great sources of information about C++/CX, and I certainly don't intend for a simple series of blog articles to replace them, so before we begin digging into C++/CX, I wanted to start with a roundup of those resources.

First, if you're interested in the rationale behind why the C++/CX language extension were developed and how the C++/CLI syntax ended up being selected for reuse, I'd recommend Jim Springfield's post on this blog from last year, "Inside the C++/CX Design". Also of note is episode 3 of GoingNative, in which Marian Luparu discusses C++/CX.

If you're new to C++/CX (or Windows Store app and Windows Runtime component development in general), and are looking for an introduction to building software with C++/CX, or if you're building something using C++/CX and are trying to figure out how to accomplish a particular task, I'd recommend the following resources as starting points:

  • Visual C++ Language Reference (C++/CX): The language reference includes a lot of useful information, including a C++/CX syntax reference with many short examples demonstrating its use. There's also a useful walkthrough of how to build a Windows Store app using C++/CX and XAML. If you're just starting out, this would be a great place to start.

  • C++ Metro style app samples: Most of the C++ sample applications and components make use of C++/CX and many demonstrate interoperation with XAML.

  • Component Extensions for Runtime Platforms: This used to be the documentation for C++/CLI, but it has since been updated to include documentation for C++/CX, with comparisons of what each syntactic feature does in each set of language extensions.

  • Hilo is an example application, written using C++, C++/CX, and XAML, and is a great resource from which to observe good coding practices—both for modern C++ and for mixing ordinary C++ code with C++/CX.

  • Building Metro style apps with C++ on MSDN Forums is a great place to ask questions if you are stuck.

Tools for Exploration

Often, the best way to learn about how the compiler handles code is to take a look at what the compiler outputs. For C++/CX, there are two outputs that are useful to look at: the metadata for the component, and the generated C++ transformation of the C++/CX code.

Metadata: As noted above, Windows Runtime requires each component to include metadata containing information about any public types defined by the component and any public or protected members of those types. This metadata is stored in a Windows Metadata (WinMD) file with a .winmd extension. When you build a Windows Runtime component using C++/CX, the WinMD file is generated by the C++ compiler; when you build a component using C++ (without C++/CX), the WinMD file is generated from IDL. WinMD files use the same metadata format as .NET assemblies.

If you want to know what types have been fabricated by the C++ compiler to support your C++/CX code, or how different C++/CX language constructs appear in metadata, it is useful to start by inspecting the generated WinMD file. Because WinMD files use the .NET metadata format, you can use the ildasm tool from the .NET Framework SDK to view the contents of a WinMD file. This tool doesn't do much interpretation of the data, so it can take some getting used to how it presents data, but it's very helpful nonetheless.

Generated Code: When compiling C++/CX code, the Visual C++ compiler transforms most C++/CX constructs into equivalent C++ code. If you're curious about what a particular snippet of C++/CX code really does, it's useful to take a look at this transformation.

There is a top-secret compiler option, /d1ZWtokens, which causes the compiler to print the generated C++ code that it generated from your C++/CX source. (Ok, this compiler option isn't really top secret: Deon Brewis mentioned it in his excellent //BUILD/ 2011 presentation, "Under the covers with C++ for Metro style apps." However, do note that this option is undocumented, and thus it is unsupported and its behavior may change at any time.)

The output is intended for diagnostic purposes only, so you won't be able to just copy and paste the output and expect it to be compilable as-is, but it's good enough to demonstrate how the compiler treats C++/CX code during compilation, and that makes this option invaluable. The output is quite verbose, so it is best to use this option with as small a source file as possible. The output includes any generated headers, including the implicitly included <vccorlib.h>. I find it's often best to use types and members with distinctive names so you can easily search for the parts that correspond to your code.

There are two other useful compiler options, also mentioned in Deon's presentation, which can be useful if you want to figure out how class hierarchies and virtual function tables (vtables) are laid out. The first is /d1reportAllClassLayout, which will cause the compiler to print out the class and vtable layouts for all classes and functions in the translation unit. The other is /d1reportSingleClassLayoutClyde which will cause the compiler to print out the class and vtable layouts for any class whose name contains "Clyde" (substitute "Clyde" for your own type name). These options are also undocumented and unsupported, and they too should only be used for diagnostic purposes.

Next Up...

In our next article (which will be the first "real" article), we'll introduce a simple C++/CX class and discuss how it maps to the Windows Runtime ABI.  The following is a list of all of the articles in this series that have been published so far:

  • @Mayuresh Kathe:

    Answer most probably is *no*.  (New version is out there - VS 2012)

  • @dissapointed_with_Very_Slow_and_Fake_C++ good news guys, embarcadero will ship later this year a XE3 which will have far superior C++ support to what Very Slow offers, and funny enough, we will be able to create our "Metropolis" UI style app using C++11 - no C++/Cx craap. How great is this?!

  • @atch666: Not. Because you don't need CX for Metro if you don't mind verbose COM code. So either you'll write COM code or use extensions regardless of IDE in use.

  • @Klimax writing code for Metro without CX is incredibly inefficient. I do mind verbose COM code, I think most people do. And what this "Not" of yours was about? Not what?

  • Guys, you will be much more tolerant to C++/CX when you see async/await constructs in it.

  • @atch666: "Not" was answer to your question. Since there is promise of no CX in other toolkit then it's clear  it will use it's own  extensions to hide COM verbosity. Or at best crazy set of macros and classes (maybe with help of ATL). (Maybe similar style as wxWidgets or QT...) Importing nice set of problems... (including problems with performance)

    Also funilly enough AFAIK all C++ compilers have their own extensions to C++.

  • @tivadj2

    What do you mean by async/await? From the name I assume this is something like task::then in PPL or futures in c++11?

    @Klimax

    The problem is you don't need "crazy set of macros and classes" to hide COM verbosity. Look at What Qt(not QT) does in e.g. QAxWidget class. You barely even know it's COM and everything is nicely hidden under the hood of a very slick library with just a handful of methods. No need for macros, exceptions, hresults or compiler extensions. Just plain old c++. And honestly I can't believe there are any performance benefits from c++/cx approach over a library approach.

  • @Krzysztof Kawa: Qt has own language extensions, isn't it?

  • @Alex no, Qt doesn't have it's language extension. I assume that you are referring to moc but this has nothing to do with language extension - you can write 100% ISO C++ in Qt. You are not forced to do anything else, by forced I mean if you don't chose "their" way you will suffer. Just like you suffer if you don't want to use Cx.

  • @tivadji intel's tbb does this and much more, much better, and interestingly - it's pure C++

  • @klimax if you study discussion between pleasefixyourbugs and james you'll see that everything can be done in iso c++ (what james himself confirms)

  • @atch666 there is no 'slots', 'Q_OBJECT', etc. keywords in ISO C++. So it is obviously a language extension. It doesn't matter if it is implemented as custom preprocessor or built-in into compiler. C++/CX also could be implemented in preprocessing stage but integrating it into compiler simplifies life a lot.

  • @Alex, the point is that Qt doesn't introduce new mutated syntax. You still CAN use multiple inheritance, regular pointers etc, YOU as  a dev. are not forced while working in Qt to go out of ISO, you don't even have to use their so called "keywords" - they are simply macros and you don't want to tell me that defining a macro is creating language extension, do you?

    On the other hand if you want to write Metro apps you more less FORCED to use CX. Try to not use it and then you'll see what I mean by being forced.

  • @atch666, what's the point of not using CX? The only thing I dislike in CX is that it is not supported in traditional desktop apps.

  • @Alex Being locked in, not being std conformant (hey those standards are made with many purposes), portability etc, etc.

    It is like asking why on earth would I want to be standard conformant, why on bloody hell would I care and write my code according to good coding practices and so on and so on. It is as simple as that.

Page 2 of 5 (65 items) 12345