Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Under the Hood Part 2: C++ WinRT Component DLL & C# Metro Application

0.00/5 (No votes)
8 Mar 2012CPOL5 min read 24.8K  
C++ WinRT component DLL and C# Metro application

We have developed a C++ WinRT Component DLL & C#.NET application in the post here:

The important point here is that the C# application is accessing the C++ WinRT component through RCW mechanism. The same application can be developed with JavaScript also that can use the C++ DLL that we developed. Wow, cool right?

To understand the simplicity of the new programming model, we created a C++ WinRT Component DLL in part 1, which is all the code you need to author a Windows Runtime component.

Please download the code and extract the files.

C#
#pragma once

using namespace Windows::Foundation;
 
namespace CppWinRTComponentDll
 { 
    public ref class CalculatorSample sealed
     {
     public:
         int Add(int x, int y);
         int Sub(int x, int y);
         int Mul(int x, int y);
 
    };
 }

In this example, you will immediately notice some keywords that are not part of standard C++. Visual C++ defines a few Component Extensions that, in a Metro style app, are essentially syntactic sugar over the underlying COM calls involved in creating and consuming Windows Runtime types. You typically use these extensions in the public interfaces where your code is passing Windows Runtime types back and forth across the ABI to JavaScript, C#, or Visual Basic (or even another C++ module). Visual C++ provides a variety of implicit conversions between Windows Runtime types and standard C++ types. The typical pattern is to use standard C++ types and libraries internally as usual, and convert to Windows Runtime types in the public interfaces.

So how did the C++ component get pulled into .NET application? When we build the CppWinRTComponentDll project, we see the following in the output window. Notice the highlighted CppWinRTComponentDll.winmd text. This means the compiler is generating a file of type windmd.

1>—— Build started: Project: CppWinRTComponentDll, Configuration: Debug Win32 ——    
1>  CppWinRTComponentDll.vcxproj -> 
C:\Users\Kishore\Documents\Visual Studio 11\Projects\CppWinRTComponentDll With 
CSharp App\Debug\CppWinRTComponentDll\CppWinRTComponentDll.winmd     
1>  LINK : C:\Users\kishore\Documents\Visual Studio 11\Projects\CppWinRTComponentDll 
With CSharp App\Debug\CppWinRTComponentDll\CppWinRTComponentDll.dll not found or 
not built by the last incremental link; performing full link     
1>     Creating library C:\Users\kishore\Documents\Visual Studio 11\Projects\CppWinRTComponentDll 
With CSharp App\Debug\CppWinRTComponentDll\CppWinRTComponentDll.lib and object 
C:\Users\kishore\Documents\Visual Studio 11\Projects\CppWinRTComponentDll With 
CSharp App\Debug\CppWinRTComponentDll\CppWinRTComponentDll.exp     
1>  CppWinRTComponentDll.vcxproj -> C:\Users\kishore\Documents\Visual Studio 11\
Projects\CppWinRTComponentDll With CSharp App\Debug\CppWinRTComponentDll\CppWinRTComponentDll.dll     
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

You can notice the CppWinRTComponentDll.winmd file in the debug folder (CppWinRTComponentDll With CSharp App\Debug\CppWinRTComponentDll) as shown in Figure 1.

image

Figure 1: .WinMD File present in CppWinRTComponentDll folder inside the Debug folder.

This WinMD file is essentially a CLI meta data file and can be opened in ILDASM as shown in figure 2. CppWinRTComponentDll is exposed using API metadata present in CppWinRTComponentDll.winmd file. The format of WinMD file is Ecma-335 and this is the same format used by the .NET Framework. It just used the ECMA-335 file format standard & the framework and nothing more than that. The underlying binary contract makes it easy for us to access the CppWinRTComponentDll APIs directly in the development language of our choice. The shape and structure of the CppWinRTComponentDll APIs can be understood by both static languages such as C# and dynamic languages such as JavaScript. IntelliSense is available in JavaScript, C#, Visual Basic, and C++ as you can see in the C# application (CSharpApplication project).

image

Figure 2: Opening CppWinRTComponentDll.winmd file using ILDASM.

This CppWinRTComponentDll.winmd file is created by C++ compiler and this can be seen as a cross language header file because C# cannot understand C++ header and neither JavaScript. So we need to have the file format that all languages understand and that is the .winmd file format. Although we authored a CalculatorSample class, what the compiler did for us is that, it also created an interface __ICalculatorSamplePublicNonVirtuals as shown in figure 3, which is the com interface used to talk to the calculator class. This adds it to the public surface.

image

Figure 3: Interface ICalculatorSamplePublicNonVirtuals created by the compiler

Manifest of the CppWinRTComponentDll.winmd file can be seen in figure 4.

image

Figure 4: Manifest of the CppWinRTComponentDll.WinMD File. Note the first entry, mscorlib.

We can see the Add method signature stored in the WinmD file in figure 5.

image

Figure 5: Add method signature present in CppWinRTComponentDll.winmd file.
C#
.method public newslot abstract virtual instance int32        
Add(int32 x,         
int32 y) cil managed         
{         
} // end of method __ICalculatorSamplePublicNonVirtuals::Add

In the ILDASM, click on the .class interface private abstract auto ansi windowsruntime. The GUID attribute. this is like specifying the GUID of the interface as shown in figure 6. This is the GUID for the component.

image

Fig 6: GUID of the interface.

The WinMD file does not contain any IL. This is just like a header information so that other languages can understand. This makes the Projections happen. The calculator is a ref class itself. The CppWinRTComponentDll.CalculatorSample class implements from .__ICalculatorSamplePublicNonVirtuals and it implements Add, Sub and Mul methods as shown in the following figure 7.

image

Fig 7: CppWinRTComponentDll.CalculatorSample class implements from __ICalculatorSamplePublicNonVirtuals Interface.

Note that every object inside WinRT is ref counted.

Details about the C++ WinRT Component DLL created in part 1 (MSDN): C++/CX (Component Extensions)

Visual C++ in Visual Studio 11 has a new programming model for creating Metro style apps and components. One of the primary features of the new model is the abstract binary interface, or ABI, which defines an interface for inter-language communication. In Windows Developer Preview, native C++ can communicate across the ABI with JavaScript and with the managed .NET languages C# and Visual Basic. This means you can create high-performance components in native C++ and consume them directly from one of these other languages. It also means you can consume Windows Runtime types directly in native C++, without having to interop with a managed layer as when you consume .NET Framework types.

At a low level, the new programming model is based on an updated version of COM, but the way that you program against this new model is more simple and natural than old-style COM programming. When you create a consumable Windows Runtime components or Metro style apps in native C++, you work primarily with classes and members just as in standard C++. JavaScript or .NET code instantiates your object by using new (or New) and the object is destroyed according to the mechanisms of the client language. When native C++ consumes a Windows Runtime object, destruction is handled by means of reference counting.

Download the code and extract the files.

"Cultivate optimism by committing yourself to a cause, a plan or a value system. You’ll feel that you are growing in a meaningful direction which will help you rise above day-to-day setbacks." — Dr. Robert Conroy

Note: The code is developed using Windows 8 & Visual Studio 2011 developer preview, which might change when the actual versions are released.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)