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:

  • Just curious, does that mean there are now *2* people working as library developers? Although great to know a well known SOer is on the team. :)

  • Oh, goody.  We have the same non-standard, unportable syntax extensions only now they mean something completely different.  And you're thankful for this?

  • As has been proved in the post I provide link to, C++/Cretinus eXperimentus was not needed, syntax was crafted for the .NET crowd, C++ devs were nowhere in the picture while this totally unnecessary MUTATION, yes, MUTATION not extension was designed, and now we (C++ devs) are told to be greateful. What a joke!

    Here is the link (mostly pay attention to exchange between Jim Springfield and PleaseFixYourBugs):

    Why Cretinus eXperimentus proved to be pointless:

    blogs.msdn.com/.../10228473.aspx

  • Guys: I don't understand your negative attitude toward C++/CX extensions. You can still use standard C++ with WRL, but the code you have to write with this WRL library solution seems to me more complex than the code you write using C++/CX.

    And using "portability" as an argument for standard C++ in this case does not make sense, since you are targeting a specific platform (Metro/WinRT), so you don't care about cross platform in this case.

    After all, C++ is an "extension" to C: you can still write virtual functions with v-tables, function pointers, etc. in pure C, but you have to write lots of boilerplate code; having the "virtual" keyword available in the C++ language helps a lot in writing simpler code. To me, the same applies for C++/CX and WinRT programming: when the code becomes very complex and boilerplate (the case of C++ with WRL), then this is a red-flag that maybe some "extension" to the language is required to make the code simpler again (in this case C++/CX).

    And you can still use pure C++ in the remaining part of the app/component; C++/CX is just for the boundary.

  • @GiovanniD As explained in the link I've provided in my previous post, CX was not necessary, the same can be done using std C++ constructs, and those constructs DO NOT HAVE TO BE MORE COMPLICATED than CX Mutations. The point is that everything could be done with C++ while preserving maintainability of code and not having boilerplate code - this topic was already discussed between herb sutter and PleaseFixYourBugs, where herb sutter argued that C can be used for everything and C++ is unnecessary - THIS IS NOT THE CASE with CX. CX mutation has been invented purely for .NET crowd to suit their habits. There was number of discussion which prove this point, I don't have link for them but if the need be I'll find them. Just to point you out if you'd like to check them for yourself and see arguments on both sides (which always ended with silence and embarrasment on CX side), look for discussion between PleaseFixYourBugs and herb sutter, and between Charles and some guy who tried (and succeed) to wrap WRL in C++ constructs - both discussion have consensus that CX is simply unnecessary, doesn't bring anything new, doesn't make anything easier. It's purely there because MS wanted for this or the other reason.

  • GiovanniD: while I wouldn't throw as much hatred and bile at it as some others, I do think C++/CX is very misguided.

    It's great that they give us a simpler, cleaner way to interop with WRT. The problem is that this "simpler, cleaner" way goes far beyond what is necessary to be an interop language. Despite what the official PR statements say, C++/CX is not *designed* to be used "at the boundary". It has been designed to creep in at all levels. It is designed for you to write your application in C++/CX, and not C++ with C++/CX at the edges.

    Heck, even the people behind it have admitted as much when you pressed them a bit: yes, they *wanted* to create a language that you could use at the "boundary", but they didn't actually enforce this, and they didn't test it by writing their own applications in C++ with C++/CX at the edges. Their actual use cases, the example code they wrote and experimented with, was C++/CX throughout.

    There are a number of simple changes that could have been done to make it a reasonable interop/boundary language. The most obvious is just giving C++/CX its own filetype extension. Make it clear to the compiler which language each file is (.cpp -> C++, and .cx (or something) -> C++/CX). But no, the didn't, which gives you no real way to *enforce* your "boundary" policy. Several of the extensions added are also completely unnecessary for the stated goal of being used for interoperability. (for example, partial classes serve no purpose in that context. But they were added because "well, our UI designers expect to have them, and we'd rather extend the language than redesign those".

    And despite what you may think, "portability" is certainly an argument.

    What if I write a cross-platform application which, among other things, should compile to WinRT? I certainly want as much of the code as possible to be as portable as possible then.

    But there's also the flip side: what if I get tired of waiting for the MSVC team to bring their compiler up to date? They *promise* that VS2012 will be different, that *this time* we will get regular out-of-band updates with new features and everything. But what if I just wanted to compile an application with Clang, and target WinRT? Can you give me a reason why that should not be possible?

    My problem with C++/CX is not what they *intended* it to be, and what they *claim* it is. My beef is with what it *actually* ended up being: yet another blob of proprietary nonstandard C++ extensions which are mashed into the C++ compiler without giving it any way to distinguish and keep them separate.

    I'm already sick of VS2010's faux keyword treatment of words like "event" or "interface" or a number of others, and I'm not looking forward to adding to the pile of "things that might have had some special meaning if this code was to be considered Microsoft Proprietary C++ dialect of the week", and therefore cannot be handled correctly by the IDE, by Intellisense or by the compiler if I'm *not* using that dialect, if I'm just writing ISO C++.

    The reason I and many others dislike C++/CX is because it demonstrates an incredible disregard and contempt for the language their compiler is named after. I don't mind language extensions, but I object to language extensions which don't even *try* to play nice, which don't respect that while they may have their uses in some situations, they're not *always* welcome, and (for some of the CX extensions, but not all) which were added when it wasn't strictly necessary.

  • @GiovanniD also if you read carefuly exchange between PleaseFixYourBugs and Jim Springfield, in one of his post Jim actually admits when put on the spot that:

    a) Everything could be done with C++ while preserving maintainability of code and not having boilerplate code

    b) THE ONLY reason that CX was concieved in favour of C++ was that they (MS) felt that it will be better received by their customers.

    herb sutter somewhere as his only argument for CX could come up with was that it will be, how he put it: "Better looking in debugger", which of course pissed many people and he was basically booed down.

    Now answer to yourself a question: Who do you think is the main customer (with regards to developers power) for a MS?

  • Pretty sure you're not meant to call it "Metro" any more...

  • I came into the comment section just to say I'm pleased to learn how c++/cx really works. I've read other comments complaining against c++/cx. I don't like c++/cx, but we have to use this "c# in c++" mix to create winrt apps. I think MS believes that c++ can only be used to create winrt components. The c++/cx compiler is designed for that. The Windows Team needed that to create winrt. I Hope this will change. But crossing an Abi boundary is not easy. Remember the win32 SendMessage method. Try this : write some code that populates a listbox in win32 (sendmessage) and winrt (^), and compare the codes. Not sure which one is nicer/better. Maybe we are missing some c++wrapper classes, à la MFC.

  • Okay, those of you who are upset that Microsoft went the C++/CX route, point taken.  But the decision was made, and we're stuck with it, and some people are going to find C++/CX worthwhile and would like to learn how to use it and post comments asking questions about how to use it.  That will be easier if the comments aren't filled up by people making the same point over and over again about how stupid an idea C++/CX is.  

  • @Jesse:  No, we have a whole team of people working on the Visual C++ libraries.

    @Tom:  I mean what I said:  I had heard much about support for C++, and my first thought upon seeing the samples was that it was actually C++/CLI and that maybe there wasn't support for native code.  I am thankful that there is support for native code :-)

    @jon:  The places it is used in this article are all the titles of other pages on MSDN.  If those pages are renamed or moved, I'll come back and update the links.

    @atch666, @grumpy:  As you have noted, the pros and cons of the decision to develop C++/CX have already been discussed in some depth, in comments both here on this blog and in reply to a handful of Channel 9 videos on the subject.  It is not my intent to reargue those points.  Some people really like working with C++/CX; other people appear to think that the development of C++/CX is the worst thing to happen in the history of programming.

    Visual C++ provides two options for building Windows Runtime components with C++:  one is via the C++/CX language extensions, the other is via the WRL library and MIDL.  If you want to build a Windows Runtime component, you can use either of them.  I've done a fair amount of both, and I know there are tradeoffs to using each of them.

    As explained in the article, the intent of this series of articles is to explain some of how C++/CX works and how C++/CX corresponds to C++ (sans-hats, using WRL), by walking through roughly equivalent code samples implemented using each.  I'm interested in using this series of articles to discuss the technical aspects of C++/CX.  I am not here to tell you that C++/CX is the greatest thing since sliced bread; I'm just here to discuss how it works.

    @grumpy:  A brief comment concerning your paragraph starting, "I'm already sick of VS2010's faux keyword treatment of words like 'event' or 'interface' or a number of others."  In the IDE, Visual Studio 2012 offers a substantially better experience here with the new semantic colorization feature.  For example, if you declare a class named 'event', it will be colored as a class, not a keyword.  The same applies to other non-C++ keywords and contextual keywords.  'interface' is still problematic in a lot of code since the combaseapi.h header defines '#define interface struct'.

  • @Pierre Morel-Fourrier  "I don't like c++/cx, but we have to use this" - Not according to James McNellis - Instead you can use WRL. Try and you'll see why WRL is not an option.

  • I'd encourage those of you interested in WRL (including those of you who are sure you already understand all that there is to know about it...) to watch this presentation by one of the designers of the library.

    channel9.msdn.com/.../The-Windows-Runtime-Library-WRL-

    Great start, James. Looking forward to the next installment!

    C

  • would vc++ 2010 express get full support for c++ 11?

  • James McNellis: wow, so just to be clear w.r.t. "fake" keywords, are we just talking about IDE Coloring, or will Intellisense also work if you have such an identifier? (I really hope `interface` will behave better as well, at least in cases where it's not `#define`d to struct (if that define is in effect, there's obviously not much to do)

    Anyway, that sounds nice. Glad to hear it has been improved.

Page 1 of 5 (65 items) 12345