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:

  • @Alex

    > So it is obviously a language extension.

    So you obviously have no idea what language extension is.

  • @atch666:

    > portability

    Metro apps are not portable to anything other than Windows 8 and Windows RT. So it makes no sense for WinRT to be portable.

  • @Alex

    I see that you also don't (fully) understand what portability means. So there is still lot of learning for you (and for all of us for that matter) but the point is that argument like yours is just silly and naive. What if I wanted to port my application written using Very Slow (VS) to embarcadero XE3? Because that's also is a portability. This is the best example why STANDARDS and CONFORMANCE to thereof is very, very important. If at one point you as a very intelligent and creative dev decided that Very Slow is just weak and doesn't give you a chance to develop your apps the way you'd like it then, if (and only if) your app was written using std language then you can simply say to folks from MS (after few years of begging them first for new features which are implemented by other vendors for years now): Screeeeww youuuu! You didn't listen to me, I just cannot allow anymore to let you (MS)constrain me and my evolution as a developer, I am... and here is the interesting thing... PORTING my business elsewhere. You see? That way you're free, that way you have a choice.

    But as the things are for now, by accepting Cx, If at one point you as a very intelligent and creative dev decided that Very Slow is just weak and doesn't give you a chance to develop your apps the way you'd like it then after years of begging MS for new features THEY will tell YOU (not in so many words of course): Screeeww youuu! We have locked you in our home brewed extension boy! You have no choice but stay with us! You are screeeewwed!

    Do you see now, why portability and conformance to standards is so important? So you want allow to anybody to enslave you.

    Regards

  • @Alex and change the "want" to "won't" from the last sentence of mine please.

  • @atch666

    > embarcadero XE3

    Do you know that C++ Builder forces you to use proprietary language extensions in every kind of GUI applications it supports? That it's standard libraries are written in Delphi? Even worse, it doesn't produce app packages that you could publish on Store. It tries to imitate Windows 8 look and feel with FireMonkey but build still produces exe files that you can run on older OS. And I would not be surprised if they doesn't integrate with Windows 8 features at all.

    Your arguments are so childish. Do you argue with your employer/team lead that way when you are forced to use tools you don't like?

  • @Alex which of my arguments are childish? And as for a workplace - this is different story, you may be sure that many MS employees don't agree with MS's policies yet they won't say anything agains. Guess why. But please answer which arguments of mine are childish and why.

  • @Alex

    Please watch more closely to what a language extension is. VCL and the likes are a library. That is a fundamental difference. I would love /CX to be implemented as a library and would have no objections whatsoever.

    What Qt does is a pre-compile step supported by any build mechanism done by tools(moc and uic) that are opensource and can be built with the same compiler you use for your code. If you want to use them with gcc, intel, vc, clang or anything else you recompile them(takes seconds) and are good to go. Also if you don't want to use their keywords like slots and signals there are macro replacements: Q_SIGNAL, Q_SLOT - still vanilla C++ code. With C++/CX no such luck. Support for it would have to be added to the compiler itself, which in case of compilers like gcc simply won't happen for reasons I think are obvious.

    On the subject of portability - it's not about running WInRT on say Linux(there's simply no point) but mainly being able to create Windows Store Apps with other compilers (mingw, intel etc.). With C++/CX in  place this is effectively impossible (WRL is not an answer, it's just horrible).

    Why would someone want to? For many reasons. Established workflow not using Visual Studio is first that comes to mind. Not having to pay for IDE or compiler is another.

  • Alex, we are not Microsoft's employees, we are their CUSTOMERS.

  • @atch666:

    I know I can use C++ without CX, but then I have to work with COM or use libs hiding it. As far as CX goes it IS extension and no matter how much you try you cannot make it to be something else to suit your own argument and/or your agenda. (Or post proof as so far you had only assertions)

    And its not like nobody else does language extensions... nor anybody forces you to use CX...

  • @Krzysztof Kawa

    > On the subject of portability - it's not about running WInRT on say Linux(there's simply no point) but mainly being able to create Windows Store Apps with other compilers (mingw, intel etc.). With C++/CX in  place this is effectively impossible (WRL is not an answer, it's just horrible).

    It is worth recalling that in standard C++ it is also impossible as C++ doesn't have standartized ABI; different compilers have different STL implementations thus you cannot just return STL type from library compiled with one compiler and consume it in code built with different compiler or with different version of same compiler (similar limitations apply to exceptions). COM and C++/CX solve these problems.

    Nobody stops you from writing wrapper library over WinRT interfaces for mingw if you need one. I don't think that caring about other compilers is something MS should do. And honestly I don't know why one would prefer mingw over msvc.

    Intel compiler is source and binary compatible with msvc. CX support will probably come soon.

    > Not having to pay for IDE or compiler is another.

    There is Visual Studio 2012 Express for Windows 8 which is free for commercial use.

  • @Alex: different ABIs is a completely different issue. I am able to build a DLL with one compiler, and load it with another. Yes, there are limitations in terms of exceptions and non-POD types and STL types, but it's doable.

    But with C++/CX you're just out of luck if you don't stick exactly to VS2012. You can't use VS2010, for example. Why not? Because "hey, it's been a long time since we invented our own proprietary language, I'm getting that itch again" Portability doesn't necessarily mean "runs on Linux". It doesn't necessarily mean "can build with GCC". It also means "Can build with the Microsoft compiler I happen to use today" Or "can build with the Microsoft compiler that's released next year". Or "can be understood by static analysis tools".

    Even if I'm a good boy who chooses to use VS2012 to build my C++/CX code, even if I'm willing to sacrifice all the C++11 features and standards-conformance that other compilers offer, even then, I have other tools than just the compiler. I might want to run  PVS Studio as my static analysis tool. I might want to run Doxygen over my source code. I might want to have syntax highlighting when viewing code in the web frontend for my source control tool. I might use Qt, which requires MOC to be able to parse the code. And so on, and so on.

    > I don't think that caring about other compilers is something MS should do.

    No. But caring about their customers is something they should do.

    > Intel compiler is source and binary compatible with msvc. CX support will probably come soon.

    "Probably". See, that's the question. Will it? Is C++/CX so well-specified that it is **possible** for other compilers to implement it? Has Microsoft committed to such a specification? Will they follow the specification if bugs in their own implementation deviates from it?

    If you're right, if it is *possible* for other compilers to implement C++/CX support, then yes, a lot of these complaints will fall away. But I see little evidence for it. When Microsoft came up with AMP, they clearly announced that "we're writing a formal specification so that anyone can implement it. We *want* third parties to implement this". With C++/CX? Not so much.

  • @Alex

    >It is worth recalling that in standard C++ it is also impossible as C++ doesn't have standartized ABI

    So your point is that inventing unportable closed-source extensions is better than pushing for standardization for anyone (including MS itself and its customers)? I strongly disagree.

    >Nobody stops you from writing wrapper library over WinRT interfaces for mingw if you need one. I don't think that caring about other compilers is something MS should do. And honestly I don't know why one would prefer mingw over msvc.

    MS stops me. I can't write a wrapper without using their compiler, which, as you pointed out yourself - might not be binary compatible with the rest of my project (if not written very carefully). While msvc is generally better compiler for windows in terms of performance or file size it's light years behind when it comes to c++11 implementation completeness and even further behind say clang in terms of debug information and static analysis. So it's a question of your needs at any particular time - binary optimisation or developer effectiveness and productivity or a decent output when you're debugging say complex templates.

    > Intel compiler is source and binary compatible with msvc. CX support will probably come soon.

    "probably" is the key here. I really have my doubts on this one. They tried this once with c++/cli and up to now only the mono project picked it up and it's hardly a widespread or popular solution.

    Btw. I never used icc myself, but wikipedia says: "(...) Since then, the compiler has been and remains compatible with GCC 3.2 and later." so I'm confused about what you said about compatibility with msvc? Do you know anything more about this?

    > There is Visual Studio 2012 Express for Windows 8 which is free for commercial use.

    Express is a no-go in any larger project. Main reason is that it doesn't support plugins so using any tools like Qt add-in or VisualAssistX or integrating with source control systems, custom build flow or bug-trackers is very hard or plain impossible compared to other freeware IDEs.

  • @grumpy summed up my primary issue with C++/CX, which is that it was introduced in a way that makes it very difficult to keep it contained in a "boundary layer" the way Sutter and other have recommended.  Co-opting the ".cpp" file extension is the most egregious example of this.  My suggestion for MS would be to designate a different extension for C++/CX (".cx" or ".ccx", perhaps), and then to add a compiler option so that the /CX extensions can be rejected in other files.

  • I'm back from an Embarcadero XE3 presentation. It doesn't do Metro: Metropolis UI is a Metro-like UI running as a desktop app (like the Zune app). Good about that? It could be deployed in Win XP (if we needed a touch-first UI in XP at all). Bad: it's still a desktop app, forget about selling it through the Store. There's no Express edition, either. Overall impression: mediocre. Disclaimer: I'm an independent developer.

  • @Diegum

    >It doesn't do Metro: Metropolis UI is a Metro-like UI running as a desktop app

    First, I can see only positives. What's wrong or what's worse in having desktop app to a Metro app? With desktop you have full power of desktop, with metro as you probably well know you are constrained in so many ways.

    Second, What do you mean it doesn't do Metro? What's Metro? AFAIC Metro is a new user interface (widely understood). If so, it is like saying, only microsoft can produce cars, others at best can produce automobiles.

    Thirdly, mediocre? fair enough, never claimed that they are fantastic, but isn't Very Slow mediocre too?

    Fourthly, the point of not being able to put it into MS store? For decades people were selling their apps without MS store, I believe that they simply don't need it. If your app is good you will sell it without MS store. If your app is bad nothing will help you, not even MS store.

    The point is that with XE3 you can have Metropolis application without being constrained in so many ways by Very Slow and CX and as you are probably aware they are going to use fantastic clang compiler which it's on its own selling point to me.

    Regards

Page 3 of 5 (65 items) 12345