Tag Archives: .net

Can you use Windows 8 WinRT API from .NET Desktop applications?

Over the course of time I received a number of comments on my blog in this area. Many questions were asked like “Can you use WinRT from Desktop applications?”, “Can you use WinRT from .NET applications?”, etc..

Well, the answer is YES. It is possible to use WinRT from Desktop applications. WinRT APIs may be tied to Metro style apps, Desktop apps or potentially available to both. The documentation will list which environments (Desktop, Metro style or both) a given API works in.

Note: Custom WinRT components are only supported in Metro style applications. They are not supported in Desktop applications.

For ex, WinRT has an API for Accelerometer. The Accelerometer class represents an accelerometer sensor which returns G-force values with respect to the x, y, and z axes.

Namespace: Windows.Devices.Sensors namespace
Class: Accelerometer

If we open the API documentation at http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.sensors.accelerometer.aspx, see the section Applies to: Metro style apps | desktop apps. Which means this class works in Metro Apps as well as desktop apps.

image

Figure 1: MSDN documentation showing WinRT API and it’s applies to section.

Advertisements

Internals (Deep dive) of Metro Application calling WinRT Component DLL

We have created a C++ XAML application that consumes the WinRT C++ DLL in part 1

we have seen the compiler generated components when we compile a WinRT Component DLL.  Part2  discusses how the C# application interacts with the C++ WinRT component.

We have seen the packaging and installation process that happens in the background during building and deploying of the applications here Under the hood Part 3 : WinRT, Windows 8, C++, C#.NET, Metro, WinRT Component DLL

We have seen the C++ XAML application calling the C++ WinRT Component DLL here Under the hood Part 4 : C++ WinRT Component DLL & C++ XAML application – WinRT, Windows 8, C++, Metro

Part5 discusses developing JavaScript application that consumes WinRT Component DLL

Lets dig deeper into how the C++ Application makes  a call across the WinRT Application Binary Interface to access the class methods inside the WinRT DLL. The slide in fig 1 is taken from the build conference which shows the internals of the method calls. We will examine the ABI and how C++ compiler extensions help reference that ABI without exposing the internal details of dealing with COM interfaces and COM activation.

Download the source code from here.

image

Fig 1: Slide showing the flow of the method calls across the boundaries.

A WinRT component implements the IInspectable interface, which is derived from IUnknown. IInspectable is used by the dynamic language bindings from JavaScript. Given a reference to a WinRT component, the JavaScript interpreter can call the IInspectable::GetRuntimeClassName method and obtain the fully-qualified class name of the WinRT component. Using the namespace name the interpreter can ask Windows to load the metadata file (.winmd) describing the component, and from the metadata determine how to use the interfaces implemented by the component.

When WinRT components are accessed from C++ or from .NET languages, there is no need for the IInspectable interface – IUnknown::QueryInterface suffices for all intents and purposes. In fact, .NET “interop” with WinRT relies on simple COM interop – an RCW created by the CLR manages the lifetime of the underlying WinRT component. For C++ language bindings, the story is somewhat more complicated, and the language extensions come into play.

The left side in Fig 1 is the C++ client application code which calls the method in right side WinRT DLL. So here if the method in C++ DLL throws an exception, it should be caught by the C++ application. But it’s not a good practice throw exceptions directly across boundaries.

The left side call (C++ Client App: Consumer) to Add() method causes the compiler to create an inline native to COM wrapper method. Also, on the left hand side, COM HRESULTs are converted to exceptions and COM “retval” arguments are converted to return values. The Add() method makes a call to this wrapper method. This inline methods generated will be something like a COM method that we write in COM components. We can see the source code generated by the compiler using some compiler switch options. we have seen the compiler generated components for making the C# application access the C++ WinRT component here Under the hood Part 2 : C++ WinRT Component DLL & C#.NET Metro application.

From the WinMD file, the C++ application knows the WinRT API signature(shown at the top of the slide) and makes the appropriate call across the WinRT ABI.

HRESULT __stdcall Add(Calculator* this, int i, int j, int * result)

//On the LHS Application, the native to COM Wrapper is as follows (Consumer-side stub pseudo-code) . See the last section of this post to see the compiler generated code. 
inline int Add(int i, int j) {
int res;
HRESULT hr = __cli_Add(this, i, j, &res);
if (hr != 0) {

__throw_hr_as_exception(hr); }
return res;
}

On the right hand side too (C++ Component DLL), C++ compiler generates inline functions. Also, WinRT and C++ exceptions are converted to HRESULTs and return values are converted to “retval” arguments. Note that the only HRESULT, which does not represent an exceptional condition, is S_OK (numeric value 0). No more positive HRESULTs (such as S_FALSE) that need to be checked explicitly by the caller.

//On the RHS C++ Component, COM to Native Wrapper stub pseudo-code is as follows:
HRESULT __stdcall ___cli_Add(Calculator* calc,
int i, int j, int* result) {
try { *result = calc->Add(i, j); }
catch(Platform::Exception^ e) { return e->HResult; }
return S_OK;
}

See the last section of this post to see the compiler generated code.

By the way, the inline wrappers can be called directly, bypassing the C++ language extensions.

image

The C++ language extensions (enabled by the /ZW switch) map WinRT to standard C++ patterns like constructors, destructors, class methods, and exceptions. For example, the language extensions hide the COM-style activation (RoActivateInstance) behind a constructor call (albeit with the ref new keyword), and hide reference counting (IUnknown::AddRef and Release) by automatically managing references. The syntax of these extensions is very similar to C++/CLI

Code Snippet
    CalculatorSample^ calcobj = ref new  CalculatorSample();
    txtAddResult->Text = calcobj->Add(10,20).ToString();

In the above code snippet, you can see we created the object of CalculatorSample class which is present in WinRT C++ Component using ref new. If you know COM, this is something like cocreateinstance() but its more than that. For now, use ref new to create objects of WinRT classes.

Let us see how to skip to exception wrapper and directly calling the Add() method present in WinRT Component. Every function in the class has a low level equivalent inside the class and currently it is prefixed with __cli_ and it takes the output as last parameter. So using ToString() on an integer. So this is another way of calling the methods inside the WinRT components. If we need HResult, we need reference to windows.h. For that include Windows.h in pch.h file as shown below.

Code Snippet
//
// pch.h
// Header for standard system include files.
//

#pragma once

#include <Windows.h>
#include "App.xaml.h"

The complete code to call the WinRT component method is as follows.

Code Snippet
MainPage::MainPage()
{
    InitializeComponent();

    CalculatorSample^ calcobj = ref new  CalculatorSample();
    //txtAddResult->Text = calcobj->Add(10,20).ToString();

    // declare a stack variable to hold the value of the result
    int result;
    //call into  calc object low level __cli_Add() but no intellisense in this preview
    HRESULT hr = calcobj->__cli_Add(10,20,&result);

    //typedef HRESULT (__std

    txtAddResult->Text = result.ToString();
}

 

Another (3rd) way is to use function pointers and call the methods using pointers. Basically, we we can take the calculator^ object, which is a pointer to a pointer to a vtable and reinterpret cast it so that it has a pointer to virtual function, which are vtables. Then we can find out the location of the method we need to call using some compiler switches which I will show below. For the Add function, we are going to specifically pick the sixth function of that and call into it. In the class layout mentioned below, I highlighted the member at 6th location. reinterpret_cast takes the calcobj ^ and cast it to a pointer to a pointer, that’s it. This is how the functions inside the components are called internally at a low level.

Code Snippet
MainPage::MainPage()
{
    InitializeComponent();

    CalculatorSample^ calcobj = ref new  CalculatorSample();
    //txtAddResult->Text = calcobj->Add(10,20).ToString();

    // declare a stack variable to hold the value of the result
    int result;
    //call into  calc object low level __cli_Add() but no intellisense in this preview
    //HRESULT hr = calcobj->__cli_Add(10,20,&result);

    //create a c function that actually represent an ABI call we will be making
    //to add function which takes this pointer, 2 input parameters and an out parameter.
    typedef HRESULT (__stdcall* AddFunc_t) (CalculatorSample^ calc, int i, int j, int * result);
    //now we can take the calculator^ object, which is a pointer to a pointer to a vtable
    //and reinterpret cast it so that it can say ok now i have a pointer of  virtual function
    //which are vtables and i am going to specifically pick the sixth function of that and call into it.
    //reinterpret_cast takes the calcobj ^ and cast it to a pointer to a pointer
    AddFunc_t* addFunc = *reinterpret_cast<AddFunc_t**>(calcobj);
    addFunc[6](calcobj,10,20, &result);

    txtAddResult->Text = result.ToString();
}

Basically a hat is a pointer to a pointer to an array of function pointers, which is Pointer to vptr to vtable. Hat (^) provides automatic reference counting.

To find out the class layout, use the /d1reportSingleClassLayout<class name> compiler switch option. Right click on the WinRTComponent.cpp file in C++ WinRT Component DLL project and select Command Line which is under C/C++. In the Additional Options, mention /d1reportSingleClassLayoutCalculatorSample, click ok and compile the project. See the output window for the magic. There is also another option to see all classes layout by using the option /d1reportAllClassLayout.

image

 

1>—— Rebuild All started: Project: CppWinRTComponentDll, Configuration: Debug Win32 ——
pch.cpp
WinRTComponent.cpp
class __ICalculatorSamplePublicNonVirtuals    size(4):
    +—
    | +— (base class Object)
0    | | {vfptr}
    | +—
    +—

__ICalculatorSamplePublicNonVirtuals::$vftable@:
    | &__ICalculatorSamplePublicNonVirtuals_meta
    |  0
0    | &Object::__cli_QueryInterface
1    | &Object::__cli_AddRef
2    | &Object::__cli_Release
3    | &Object::__cli_GetIids
4    | &Object::__cli_GetRuntimeClassName
5    | &Object::__cli_GetTrustLevel
6    | &__ICalculatorSamplePublicNonVirtuals::__cli_Add
7    | &__ICalculatorSamplePublicNonVirtuals::Add

__ICalculatorSamplePublicNonVirtuals::Add this adjustor: 0
__ICalculatorSamplePublicNonVirtuals::__cli_Add this adjustor: 0

class __CalculatorSampleActivationFactory    size(12):
    +—
    | +— (base class IActivationFactory)
    | | +— (base class Object)
0    | | | {vfptr}
    | | +—
    | +—
    | +— (base class Object)
4    | | {vfptr}
    | +—
8    | __cli_MultiThreadedRefCount __cli_refcount
    +—

__CalculatorSampleActivationFactory::$vftable@Object@:
    | -4
0    | &thunk: this-=4; goto __CalculatorSampleActivationFactory::__cli_QueryInterface
1    | &thunk: this-=4; goto __CalculatorSampleActivationFactory::__cli_AddRef
2    | &thunk: this-=4; goto __CalculatorSampleActivationFactory::__cli_Release
3    | &thunk: this-=4; goto __CalculatorSampleActivationFactory::__cli_GetIids
4    | &thunk: this-=4; goto __CalculatorSampleActivationFactory::__cli_GetRuntimeClassName
5    | &thunk: this-=4; goto __CalculatorSampleActivationFactory::__cli_GetTrustLevel

__CalculatorSampleActivationFactory::$vftable@IActivationFactory@:
    | &__CalculatorSampleActivationFactory_meta
    |  0
0    | &__CalculatorSampleActivationFactory::__cli_QueryInterface
1    | &__CalculatorSampleActivationFactory::__cli_AddRef
2    | &__CalculatorSampleActivationFactory::__cli_Release
3    | &__CalculatorSampleActivationFactory::__cli_GetIids
4    | &__CalculatorSampleActivationFactory::__cli_GetRuntimeClassName
5    | &__CalculatorSampleActivationFactory::__cli_GetTrustLevel
6    | &__CalculatorSampleActivationFactory::__cli_Platform_IActivationFactory____cli_ActivateInstance
7    | &__CalculatorSampleActivationFactory::ActivateInstance

__CalculatorSampleActivationFactory::ActivateInstance this adjustor: 0
__CalculatorSampleActivationFactory::__cli_QueryInterface this adjustor: 0
__CalculatorSampleActivationFactory::__cli_AddRef this adjustor: 0
__CalculatorSampleActivationFactory::__cli_Release this adjustor: 0
__CalculatorSampleActivationFactory::__cli_GetIids this adjustor: 0
__CalculatorSampleActivationFactory::__cli_GetRuntimeClassName this adjustor: 0
__CalculatorSampleActivationFactory::__cli_GetTrustLevel this adjustor: 0
__CalculatorSampleActivationFactory::__cli_Platform_IActivationFactory____cli_ActivateInstance this adjustor: 0

class CalculatorSample    size(12):
    +—
    | +— (base class __ICalculatorSamplePublicNonVirtuals)
    | | +— (base class Object)
0    | | | {vfptr}
    | | +—
    | +—
    | +— (base class Object)
4    | | {vfptr}
    | +—
8    | __cli_MultiThreadedRefCount __cli_refcount
    +—

CalculatorSample::$vftable@__ICalculatorSamplePublicNonVirtuals@:
    | &CalculatorSample_meta
    |  0
0    | &CalculatorSample::__cli_QueryInterface
1    | &CalculatorSample::__cli_AddRef
2    | &CalculatorSample::__cli_Release
3    | &CalculatorSample::__cli_GetIids
4    | &CalculatorSample::__cli_GetRuntimeClassName
5    | &CalculatorSample::__cli_GetTrustLevel
6    | &CalculatorSample::

__cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add
7    | &CalculatorSample::Add

CalculatorSample::$vftable@Object@:
    | -4
0    | &thunk: this-=4; goto CalculatorSample::__cli_QueryInterface
1    | &thunk: this-=4; goto CalculatorSample::__cli_AddRef
2    | &thunk: this-=4; goto CalculatorSample::__cli_Release
3    | &thunk: this-=4; goto CalculatorSample::__cli_GetIids
4    | &thunk: this-=4; goto CalculatorSample::__cli_GetRuntimeClassName
5    | &thunk: this-=4; goto CalculatorSample::__cli_GetTrustLevel

CalculatorSample::Add this adjustor: 0
CalculatorSample::__cli_QueryInterface this adjustor: 0
CalculatorSample::__cli_AddRef this adjustor: 0
CalculatorSample::__cli_Release this adjustor: 0
CalculatorSample::__cli_GetIids this adjustor: 0
CalculatorSample::__cli_GetRuntimeClassName this adjustor: 0
CalculatorSample::__cli_GetTrustLevel this adjustor: 0
CalculatorSample::__cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add this adjustor: 0

Analyzing the layout:

Every WinRT object is laid out in the following way. The first 3 methods in the Vtable are from IUnknown and the next 3 interfaces methods are there for dynamic languages. The important one is GetRuntimeClassName and it allows JavaScript to call into .net  obtain the fully-qualified class name of the WinRT component. When JavaScript calls GetRuntimeClassName, it returns  CppWinRTComponentDll. CalculatorSample. JavaScript then goes and finds out which WinMD file in the system has the classname CppWinRTComponentDll.CalculatorSample. so Windows 8 will inform that it is inside CppWinRTComponentDll.DLL. It then loads the WinMD file of CppWinRTComponentDll.DLL and calls the Add function inside it. In C++, we don’t use these methods as we can directly interact with the class. It doesn’t do dynamic dispatch.

0 | &CalculatorSample::__cli_QueryInterface
1 | &CalculatorSample::__cli_AddRef
2 | &CalculatorSample::__cli_Release

3 | &CalculatorSample::__cli_GetIids
4 | &CalculatorSample::__cli_GetRuntimeClassName
5 | &CalculatorSample::__cli_GetTrustLevel

6 | &CalculatorSample::

__cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add

 

Coming to the calculator class, you notice CalculatorSample is of size 12. The first vprt we have is ICalculatorSamplePublicNonVirtuals and then we have vprt to Object and then the ref count.

class CalculatorSample size(12):
+—
| +— (base class __ICalculatorSamplePublicNonVirtuals)
| | +— (base class Object)
0 | | | {vfptr}
| | +—
| +—
| +— (base class Object)
4 | | {vfptr}
| +—
8 | __cli_MultiThreadedRefCount __cli_refcount
+—

If we analyze the first vptr, it points to ICalculatorSamplePublicNonVirtuals. The layout of the interface is as follows. The first 3 methods are for IUnknown and the other 3 are IInspectable. Notice 6 and 7 are referencing the Add method we wrote in the DLL. There are here for a reason. No 7 is to support compile time inheritance. The C++ can directly call into C++.

CalculatorSample::$vftable@__ICalculatorSamplePublicNonVirtuals@:
| &CalculatorSample_meta
| 0
0 | &CalculatorSample::__cli_QueryInterface
1 | &CalculatorSample::__cli_AddRef
2 | &CalculatorSample::__cli_Release
3 | &CalculatorSample::__cli_GetIids
4 | &CalculatorSample::__cli_GetRuntimeClassName
5 | &CalculatorSample::__cli_GetTrustLevel
6 | &CalculatorSample::__cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add
7 | &CalculatorSample::Add

To understand more, let us use the compiler option. right click on WinRTComponent.cpp and add /d1ZWtokens as shown below and compile the WinRTComponent.cpp class.

image

In the output window, search for __cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add and see the inline code generated by the compiler. This gives us a better understanding of the inner workings of calling the WinRT components.

 

1>—— Build started: Project: CppWinRTComponentDll, Configuration: Debug Win32 ——
1>  WinRTComponent.cpp
1>  Declaring Member 2: __ICalculatorSamplePublicNonVirtuals::Add (int __cdecl CppWinRTComponentDll::__ICalculatorSamplePublicNonVirtuals::Add(int,int)). [isVirtual=1 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __ICalculatorSamplePublicNonVirtuals::__cli_Add (long __stdcall CppWinRTComponentDll::__ICalculatorSamplePublicNonVirtuals::__cli_Add(int,int,int *)). [isVirtual=1 isPure=1 isStatic=0]
1> 
1>  Declaring Member 4a: CalculatorSample::__cli_refcount
1> 
1>  Declaring Member 2: CalculatorSample::__cli_QueryInterface (long __stdcall CppWinRTComponentDll::CalculatorSample::__cli_QueryInterface(class Platform::Guid %,void **)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: CalculatorSample::__cli_AddRef (unsigned long __stdcall CppWinRTComponentDll::CalculatorSample::__cli_AddRef(void)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: CalculatorSample::__cli_Release (unsigned long __stdcall CppWinRTComponentDll::CalculatorSample::__cli_Release(void)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: CalculatorSample::__cli_GetIids (long __stdcall CppWinRTComponentDll::CalculatorSample::__cli_GetIids(unsigned long *,class Platform::Guid **)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: CalculatorSample::__cli_GetRuntimeClassName (long __stdcall CppWinRTComponentDll::CalculatorSample::__cli_GetRuntimeClassName(struct __cli_HSTRING__ **)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: CalculatorSample::__cli_GetTrustLevel (long __stdcall CppWinRTComponentDll::CalculatorSample::__cli_GetTrustLevel(enum __cli_TrustLevel *)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: CalculatorSample::__cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add (long __stdcall CppWinRTComponentDll::CalculatorSample::__cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add(int,int,int *)=long __stdcall CppWinRTComponentDll::__ICalculatorSamplePublicNonVirtuals::__cli_Add(int,int,int *)). [isVirtual=1 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: IActivationFactory::__cli_ActivateInstance (long __stdcall Platform::IActivationFactory::__cli_ActivateInstance(class Platform::Object ^*)). [isVirtual=1 isPure=1 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::ActivateInstance (class Platform::Object ^__thiscall CppWinRTComponentDll::__CalculatorSampleActivationFactory::ActivateInstance(void)). [isVirtual=1 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::CreateFactory (long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::CreateFactory(unsigned int *,struct __cli___classObjectEntry *,class Platform::Guid %,struct __cli_IUnknown **)). [isVirtual=0 isPure=0 isStatic=1]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::GetTargetClassName (const wchar_t *__stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::GetTargetClassName(void)). [isVirtual=0 isPure=0 isStatic=1]
1> 
1>  Declaring Member 4a: __CalculatorSampleActivationFactory::__cli_refcount
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::__cli_QueryInterface (long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::__cli_QueryInterface(class Platform::Guid %,void **)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::__cli_AddRef (unsigned long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::__cli_AddRef(void)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::__cli_Release (unsigned long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::__cli_Release(void)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::__cli_GetIids (long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::__cli_GetIids(unsigned long *,class Platform::Guid **)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::__cli_GetRuntimeClassName (long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::__cli_GetRuntimeClassName(struct __cli_HSTRING__ **)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::__cli_GetTrustLevel (long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::__cli_GetTrustLevel(enum __cli_TrustLevel *)). [isVirtual=0 isPure=0 isStatic=0]
1> 
1>  Declaring Member 2: __CalculatorSampleActivationFactory::__cli_Platform_IActivationFactory____cli_ActivateInstance (long __stdcall CppWinRTComponentDll::__CalculatorSampleActivationFactory::__cli_Platform_IActivationFactory____cli_ActivateInstance(class Platform::Object ^*)=long __stdcall Platform::IActivationFactory::__cli_ActivateInstance(class Platform::Object ^*)). [isVirtual=1 isPure=0 isStatic=0]
1> 
1>  inline function header symbol: {ctor}
1> 
1>  {
1> 
1>   
1> 
1>  }
1> 
1>  inline function header symbol: {ctor}
1> 
1>  {
1> 
1>   
1> 
1>  }
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>   inline int :: CppWinRTComponentDll :: __ICalculatorSamplePublicNonVirtuals :: Add ( int x , int y )
1> 
1>    {
1> 
1>      int __cli_returnValue ;
1> 
1>      long __hr = __cli_Add ( x , y , & __cli_returnValue ) ;
1> 
1>      __cli_WinRTThrowError ( __hr ) ;
1> 
1>      return __cli_returnValue ;
1> 
1>     
1> 
1>    }
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>    inline long __stdcall :: CppWinRTComponentDll :: CalculatorSample :: __cli_CppWinRTComponentDll___ICalculatorSamplePublicNonVirtuals____cli_Add ( int x , int y , int * __cli_returnValue )
1> 
1>    {
1> 
1>      long __hr = 0 ;
1> 
1>      * __cli_returnValue = 0 ;
1> 
1>      try
1> 
1>      {
1> 
1>        auto __tempValue = Add ( x , y ) ;
1> 
1>        * __cli_returnValue = __tempValue ;
1> 
1>       
1> 
1>      }
1> 
1>      catch ( :: Platform :: Exception ^ __param0 )
1> 
1>      {
1> 
1>        __hr = __param0 -> HResult ;
1> 
1>       
1> 
1>      }
1> 
1>      catch ( … )
1> 
1>      {
1> 
1>        __hr = -2147467259 ;
1> 
1>       
1> 
1>      }
1> 
1>      return __hr ;
1> 
1>     
1> 
1>    }
1>
 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>    long :: CppWinRTComponentDll :: CalculatorSample :: __cli_QueryInterface ( class Platform::Guid % __param0 , void ** __param1 )
1> 
1>    {
1> 
1>      if ( __param0 . Equals ( __uuidof ( __cli_IUnknown ) ) || __param0 . Equals ( __uuidof ( __cli_IInspectable ) ) || __param0 . Equals ( __uuidof ( struct CppWinRTComponentDll::__ICalculatorSamplePublicNonVirtuals ^ ) ) )
1> 
1>      {
1> 
1>        * __param1 = reinterpret_cast < void * > ( static_cast < struct CppWinRTComponentDll::__ICalculatorSamplePublicNonVirtuals ^ > ( this ) ) ;
1> 
1>        __cli_refcount . Increment ( ) ;
1> 
1>        return 0 ;
1> 
1>       
1> 
1>      }
1> 
1>      return -2147467262 ;
1> 
1>     
1> 
1>    }
1> 
1>    unsigned long :: CppWinRTComponentDll :: CalculatorSample :: __cli_AddRef ( )
1> 
1>    {
1> 
1>      long __cli_returnValue = __cli_refcount . Increment ( ) ;
1> 
1>      return ( unsigned long ) __cli_returnValue ;
1> 
1>     
1> 
1>    }
1> 
1>    unsigned long :: CppWinRTComponentDll :: CalculatorSample :: __cli_Release ( )
1> 
1>    {
1> 
1>      long __cli_returnValue = __cli_refcount . Decrement ( ) ;
1> 
1>      if ( ! __cli_returnValue )
1> 
1>      {
1> 
1>        delete this ;
1> 
1>        :: Platform :: Heap :: Free ( reinterpret_cast < void * > ( this ) ) ;
1> 
1>       
1> 
1>      }
1> 
1>      return ( unsigned long ) __cli_returnValue ;
1> 
1>     
1> 
1>    }
1> 
1>    long :: CppWinRTComponentDll :: CalculatorSample :: __cli_GetIids ( unsigned long * __param0 , class Platform::Guid ** __param1 )
1> 
1>    {
1> 
1>      struct __s_GUID __interfaceList [ ] =
1> 
1>      {
1> 
1>       
1> 
1>        {
1> 
1>          -1302793136 , 5274 , 13110 , 160 , 43 , 249 , 241 , 108 , 73 , 159 , 212
1> 
1>        }
1> 
1>       
1> 
1>      } ;
1> 
1>     
1> 
1>      return __winRT :: __winRTRuntime . __getIids ( 1 , __param0 , __interfaceList , __param1 ) ;
1> 
1>     
1> 
1>    }
1> 
1>    long :: CppWinRTComponentDll :: CalculatorSample :: __cli_GetRuntimeClassName ( struct __cli_HSTRING__ ** __param0 )
1> 
1>    {
1> 
1>      return __winRT :: __winRTRuntime . __windowsCreateString ( ( const wchar_t * ) L"CppWinRTComponentDll.CalculatorSample" , 37 , __param0 ) ;
1> 
1>     
1> 
1>    }
1> 
1>    long :: CppWinRTComponentDll :: CalculatorSample :: __cli_GetTrustLevel ( enum __cli_TrustLevel * __param0 )
1> 
1>    {
1> 
1>      * __param0 = __cli_FullTrust ;
1> 
1>      return 0 ;
1> 
1>     
1> 
1>    }
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace Platform
1> 
1>  {
1> 
1>    inline class Platform::Object ^ :: Platform :: IActivationFactory :: ActivateInstance ( )
1> 
1>    {
1> 
1>      class Platform::Object ^ __cli_returnValue ;
1> 
1>      long __hr = __cli_ActivateInstance ( & __cli_returnValue ) ;
1> 
1>      __cli_WinRTThrowError ( __hr ) ;
1> 
1>      return __cli_returnValue ;
1> 
1>     
1> 
1>    }
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>    inline long __stdcall :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: __cli_Platform_IActivationFactory____cli_ActivateInstance ( class Platform::Object ^* __cli_returnValue )
1> 
1>    {
1> 
1>      long __hr = 0 ;
1> 
1>      * __cli_returnValue = nullptr ;
1> 
1>      try
1> 
1>      {
1> 
1>        auto __tempValue = ActivateInstance ( ) ;
1> 
1>        * __cli_returnValue = __tempValue ;
1> 
1>       
1> 
1>      }
1> 
1>      catch ( :: Platform :: Exception ^ __param0 )
1> 
1>      {
1> 
1>        __hr = __param0 -> HResult ;
1> 
1>       
1> 
1>      }
1> 
1>      catch ( … )
1> 
1>      {
1> 
1>        __hr = -2147467259 ;
1> 
1>       
1> 
1>      }
1> 
1>      return __hr ;
1> 
1>     
1> 
1>    }
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>    long :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: __cli_QueryInterface ( class Platform::Guid % __param0 , void ** __param1 )
1> 
1>    {
1> 
1>      if ( __param0 . Equals ( __uuidof ( __cli_IUnknown ) ) || __param0 . Equals ( __uuidof ( __cli_IInspectable ) ) || __param0 . Equals ( __uuidof ( struct Platform::IActivationFactory ^ ) ) )
1> 
1>      {
1> 
1>        * __param1 = reinterpret_cast < void * > ( static_cast < struct Platform::IActivationFactory ^ > ( this ) ) ;
1> 
1>        __cli_refcount . Increment ( ) ;
1> 
1>        return 0 ;
1> 
1>       
1> 
1>      }
1> 
1>      return -2147467262 ;
1> 
1>     
1> 
1>    }
1> 
1>    unsigned long :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: __cli_AddRef ( )
1> 
1>    {
1> 
1>      long __cli_returnValue = __cli_refcount . Increment ( ) ;
1> 
1>      return ( unsigned long ) __cli_returnValue ;
1> 
1>     
1> 
1>    }
1> 
1>    unsigned long :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: __cli_Release ( )
1> 
1>    {
1> 
1>      long __cli_returnValue = __cli_refcount . Decrement ( ) ;
1> 
1>      if ( ! __cli_returnValue )
1> 
1>      {
1> 
1>        delete this ;
1> 
1>        :: Platform :: Heap :: Free ( reinterpret_cast < void * > ( this ) ) ;
1> 
1>       
1> 
1>      }
1> 
1>      return ( unsigned long ) __cli_returnValue ;
1> 
1>     
1> 
1>    }
1> 
1>    long :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: __cli_GetIids ( unsigned long * __param0 , class Platform::Guid ** __param1 )
1> 
1>    {
1> 
1>      struct __s_GUID __interfaceList [ ] =
1> 
1>      {
1> 
1>       
1> 
1>        {
1> 
1>          53 , 0 , 0 , 192 , 0 , 0 , 0 , 0 , 0 , 0 , 70
1> 
1>        }
1> 
1>       
1> 
1>      } ;
1> 
1>     
1> 
1>      return __winRT :: __winRTRuntime . __getIids ( 1 , __param0 , __interfaceList , __param1 ) ;
1> 
1>     
1> 
1>    }
1> 
1>    long :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: __cli_GetRuntimeClassName ( struct __cli_HSTRING__ ** __param0 )
1> 
1>    {
1> 
1>      return __winRT :: __winRTRuntime . __windowsCreateString ( ( const wchar_t * ) L"CppWinRTComponentDll.__CalculatorSampleActivationFactory" , 56 , __param0 ) ;
1> 
1>     
1> 
1>    }
1> 
1>    long :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: __cli_GetTrustLevel ( enum __cli_TrustLevel * __param0 )
1> 
1>    {
1> 
1>      * __param0 = __cli_FullTrust ;
1> 
1>      return 0 ;
1> 
1>     
1> 
1>    }
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>    class Platform::Object ^ :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: ActivateInstance ( )
1> 
1>    {
1> 
1>      return gcnew class CppWinRTComponentDll::CalculatorSample ( ) ;
1> 
1>     
1> 
1>    }
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>    long __stdcall :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: CreateFactory ( unsigned int * , struct __cli___classObjectEntry * , class Platform::Guid % __param2 , struct __cli_IUnknown ** __param3 )
1> 
1>    {
1> 
1>      class CppWinRTComponentDll::__CalculatorSampleActivationFactory ^ __pActivationFactory = gcnew :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory ( ) ;
1> 
1>      return __pActivationFactory -> __cli_QueryInterface ( __param2 , reinterpret_cast < void ** > ( __param3 ) ) ;
1> 
1>     
1> 
1>    }
1> 
1>    const wchar_t * __stdcall :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: GetTargetClassName ( )
1> 
1>    {
1> 
1>      return L"CppWinRTComponentDll.CalculatorSample" ;
1> 
1>     
1> 
1>    }
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
1>  <TokenStream>
1> 
1>  namespace CppWinRTComponentDll
1> 
1>  {
1> 
1>    const struct __cli___classObjectEntry __CalculatorSampleActivationFactory_Registration =
1> 
1>    {
1> 
1>      :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: CreateFactory , :: CppWinRTComponentDll :: __CalculatorSampleActivationFactory :: GetTargetClassName , nullptr , & __cli_no_factory_cache , nullptr
1> 
1>    } ;
1> 
1>   
1> 
1>    extern "C" __declspec ( allocate ( "minATL$__r" ) ) __declspec ( selectany ) const :: __cli___classObjectEntry * const CppWinRTComponentDll___CalculatorSampleActivationFactory__Entry = & __CalculatorSampleActivationFactory_Registration ;
1> 
1>   
1> 
1>  }
1>  </TokenStream>
1> 
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

 

The complete code of MainPage.xaml.cpp is as follows.

Code Snippet
//
// MainPage.xaml.cpp
// Implementation of the MainPage.xaml class.
//

#include "pch.h"
#include "MainPage.xaml.h"

using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace CPPApplication1;

using namespace CppWinRTComponentDll;

MainPage::MainPage()
{
    InitializeComponent();

    CalculatorSample^ calcobj = ref new  CalculatorSample();
    //txtAddResult->Text = calcobj->Add(10,20).ToString();

    //// declare a stack variable to hold the value of the result
    int result;
    //call into  calc object low level __cli_Add() but no intellisense in this preview
    //HRESULT hr = calcobj->__cli_Add(10,20,&result);

    //create a c function that actually represent an ABI call we will be making
    //to add function which takes this pointer, 2 input parameters and an out parameter.
    typedef HRESULT (__stdcall* AddFunc_t) (CalculatorSample^ calc, int i, int j, int * result);
    //now we can take the calculator^ object, which is a pointer to a pointer to a vtable
    //and reinterpret cast it so that it can say ok now i have a pointer of  virtual function
    //which are vtables and i am going to specifically pick the sixth function of that and call into it.
    //reinterpret_cast takes the calcobj ^ and cast it to a pointer to a pointer
    AddFunc_t* addFunc = *reinterpret_cast<AddFunc_t**>(calcobj);
    addFunc[6](calcobj,10,20, &result);

    ////CalculatorSample^ calcobj = ref new CalculatorSample();
    ////int* vtable_array = (int*)calcobj;
    ////int* icalc_vtable = (int*)vtable_array[0];
    ////int* compute_will_be_fptr = (int*)icalc_vtable[6];
    ////typedef HRESULT (__stdcall *compute_fptr_t)(CalculatorSample^, int, int, int*);
    ////compute_fptr_t compute_fptr = (compute_fptr_t)compute_will_be_fptr;
    ////compute_fptr(calcobj,10,20, &result);

    txtAddResult->Text = result.ToString();
}

MainPage::~MainPage()
{
}

 

Download the source code from here.

"If you limit your choices only to what seems possible or reasonable, you disconnect yourself from what you truly want, and all that is left is a compromise."

WinRT from the eyes of a .NET developer

Following is the compilation of information related to what the .NET developer need to know about WinRT.

This biggest confusion, has been around the use of the .NET Framework across the blue side and green side. The reason for the, as I call it, .NET Metro Profile is because the Metro style apps run in an app container that limits what the application can have access to in order to protect the end user from potentially malicious apps. As such, the Metro Profile is a subset of the .NET Client Profile and simply takes away some of the capabilities that aren’t allowed by the app container for Metro style apps. Developers used to .NET will find accessing the WinRT APIs very intuitive – it works similarly to having an assembly reference and accessing the members of said referenced assembly.

At the lowest level, WinRT is an object model defined on ABI level. It uses COM as a base (so every WinRT object implements IUnknown and does refcounting), and builds from there. It does add quite a lot of new concepts in comparison to COM of old, most of which come directly from .NET – for example, WinRT object model has delegates, and events are done .NET-style (with delegates and add/remove subscriber methods, one per event) rather than the old COM model of event sources and sinks. Of other notable things, WinRT also has parametrized (“generic”) interfaces.

One other big change is that all WinRT components have metadata available for them, just like .NET assemblies. In COM you kinda sorta had that with typelibs, but not every COM component had them. For WinRT, the metadata is contained in .winmd files – look inside “C:\Program Files (x86)\Windows Kits\8.0\Windows Metadata\” in Developer Preview. If you poke around, you’ll see that they are actually CLI assemblies with no code, just metadata tables. You can open them with ILDASM, in fact. Note, this doesn’t mean that WinRT itself is managed – it simply reuses the file format.

Then there are a number of libraries implemented in terms of that object model – defining WinRT interfaces and classes. Again, look at “Windows Metadata” folder mentioned above to see what’s there; or just fire up Object Browser in VS and select “Windows 8.0” in the framework selector, to see what’s covered. There’s a lot there, and it doesn’t deal with UI alone – you also get namespaces such as Windows.Data.Json, or Windows.Graphics.Printing, or Windows.Networking.Sockets.

Then you get several libraries, which are specifically dealing with UI – mostly these would be various namespaces under Windows.UI or Windows.UI.Xaml. A lot of them are very similar to WPF/Silverlight namespaces – e.g. Windows.UI.Xaml.Controls is closely matching System.Windows.Controls; ditto for Windows.UI.Xaml.Documents etc.

Now, .NET has the ability to directly reference WinRT components as if they were .NET assemblies. This works differently from COM Interop – you don’t need any intermediate artifacts such as interop assemblies, you just /r a .winmd file, and all types and their members in its metadata become visible to you as if they were .NET objects. Note that WinRT libraries themselves are fully native (and so native C++ programs that use WinRT do not require CLR at all) – the magic to expose all that stuff as managed is inside the CLR itself, and is fairly low level. If you ildasm a .NET program that references a .winmd, you’ll see that it actually looks like an extern assembly reference – there’s no sleight of hand trickery such as type embedding there.

It’s not a blunt mapping, either – CLR tries to adapt WinRT types to their equivalents, where possible. So e.g. GUIDs, dates and URIs become System.Guid, System.DateTime and System.Uri, respectively; WinRT collection interfaces such as IIterable<T> and IVector<T> become IEnumerable<T> and IList<T>; and so on. This goes both ways – if you have a .NET object that implements IEnumerable<T>, and pass it back to WinRT, it’ll see it as IIterable<T>.

Ultimately, what this means is that your .NET Metro apps get access to a subset of the existing standard .NET libraries, and also to (native) WinRT libraries, some of which – particularly Windows.UI – look very similar to Silverlight, API-wise. You still have XAML to define your UI, and you still deal with the same basic concepts as in Silverlight – data bindings, resources, styles, templates etc. In many cases, it is possible to port a Silverlight app simply by using the new namespaces, and tweaking a few places in code where the API was adjusted.

WinRT itself doesn’t have anything to do with HTML and CSS, and it bears relation to JavaScript only in a sense that it is also exposed there, similar to how it is done for .NET. You don’t need to deal with HTML/CSS/JS when you use WinRT UI libraries in your .NET Metro app (well, I guess, if you really want to, you can host a WebView control…). All your .NET and Silverlight skills remain very much relevant in this programming model.

Under the hood Part 5 : JavaScript application & C++ WinRT Component DLL – WinRT, Windows 8, C++, Metro

JavaScript application calling WinRT Component DLL

In this part, we will create a C++ WinRT Component DLL and access it from a JavaScript application.

We have developed a C++ WinRT Component DLL & C#.NET application in the post here Under the hood Part 1 : C++ WinRT Component DLL & C#.NET Metro application

we have seen the compiler generated components for making the C# application access the C++ WinRT component here Under the hood Part 2 : C++ WinRT Component DLL & C#.NET Metro application

We have seen the packaging and installation process that happens in the background during building and deploying of the applications here Under the hood Part 3 : WinRT, Windows 8, C++, C#.NET, Metro, WinRT Component DLL

We have seen the C++ XAML application calling the C++ WinRT Component DLL here Under the hood Part 4 : C++ WinRT Component DLL & C++ XAML application – WinRT, Windows 8, C++, Metro

Generally, in a LOB application, we might have to build a C++ Component DLL to take advantage of the performance of C++ in complex or computationally-intensive operations. The C++ component can access Windows operating system services that are not accessible through the Windows Runtime in the current version. Mostly, to reuse existing code that is already written and tested.

Download the source code here.

Step 1:

Create a Windows Runtime C++ Component DLL:

Open Visual Studio 2011 –> File –> New Project –> Go to Installed Templates section –> Visual C++ –>Select WinRT Component DLL and name it as CPPWinRTComponentDll as shown in the following figure.

image

Fig 1: CPPWinRTComponentDll project

Open WinRTComponent.h file and create an Employee class as shown in the following code snippet. The Platform namespace is where C++ defines its classes that are specific Windows Runtime types.

Create a private variables address_ and employeeid_. These are used as backing store to hold the values. We will use get() & set() properties to set or get these values.

    private:
            // Backing store for property address_ & employeeid_.
            Platform::String^ address_;
            int employeeid_;

 

In the public section, add the following code which are properties for the above backing store.

        property Platform::String^ Address
        {
            Platform::String^ get()
            {
                return  (address_);
            }
        }

        // Property with custom setter/getter
        property int EmployeeId
        {
            int get()
            {
                return employeeid_;
            }

            //    ‘set’ accessor is missing its value parameter
            void set(int value)
            {
                if(value <= 0)
                {
                    throw ref new Platform::InvalidArgumentException();
                    employeeid_ = value;
                }
            }
        }

 

We can also add some trivial get/set property with the compiler generating the backing store.

    public:
        // Trivial get/set property with compiler-generated backing store.
        property Platform::String^ Name;

 

Following is the complete code of the Employee class.

Code Snippet
public ref class Employee sealed
    {
    private:
            Platform::String^ address_;
            int employeeid_;
           
            //If i use a stack syntax, i get compilation error
            //Platform::String address2_;
            //Error    1    error C3149: ‘Platform::String’ : cannot use this type here without a top-level ‘^’   
            //c:\projects\cppwinrtcomponentdll with cpp app string\cppwinrtcomponentdll\winrtcomponent.h   

    public:

        property Platform::String^ Name;
        property Platform::String^ Address
        {
            Platform::String^ get()
            {
                return  (address_);
            }
        }

        property int EmployeeId
        {
            int get()
            {
                return employeeid_;
            }

            //    ‘set’ accessor is missing its value parameter
            void set(int value)
            {
                if(value <= 0)
                {
                    throw ref new Platform::InvalidArgumentException();
                    employeeid_ = value;
                }
            }
        }

    public:
        Platform::String^ SayHello()
        {
            return "Hello World";
        }

    public:
        int Add(int x, int y)
        {
            return x+y;
        }

    };

 

When you code your C++ component, if needed, you can use the regular C++ library and built-in types inside the class code except at the abstract binary interface (ABI) boundary where you are passing data to and from JavaScript. There, use Windows Runtime types and the special syntax that Visual C++ supports for creating and manipulating those types.

You have to make the Employee class as activatable class so that it can instantiated from another language such as JavaScript. To be consumable from another language such as JavaScript, a component must contain at least one activatable class. If needed, a Windows Runtime component can contain multiple activatable classes as well as additional classes known only internally to the component. Client code creates an instance of the component by using the new keyword just as for any class.

The Employee class must be declared as public ref class sealed. The ref class keywords tell the compiler to create the class as a Windows Runtime compatible type, and the sealed keyword specifies that the class cannot be inherited. A class must be sealed to be consumed by JavaScript.

In the Platform::String^ address_, the ^ operator signifies a handle to a Windows Runtime string type that under the covers is reference-counted and deleted when the count reaches zero. Instances of these types are created by using the ref new keywords. Do not explicitly call delete on these instances.

Types must be passed to and from the public methods as Windows Runtime types. If you use the C++ built-in types such as int, double and so on, the compiler will automatically convert them to the appropriate Windows Runtime type. No such conversion occurs unless you are passing the type across the ABI. Complex types such as Platform::String^ must be specified explicitly.

Step 2:

Creating a JavaScript Windows Metro style Application project:

To create a project in this solution, right-click the solution node in Solution Explorer. and select Add Project > Blank Application. Name it as WinWebApp1.

image

Fig 2: creating the JavaScript project
Add a reference to the component project

After you have compiled the C++ project for the first time, you can add it as a project reference in the JavaScript project. Right-click the References node in the JavaScript project, and select Add. When the Add References Manager dialog box appears, click “Solution” to display the available references in the solution. Select  “CPPWinRTComponentDll ” in this solution and click on Add button as shown in figure 3; The namespace and all public types and methods are now available to your JavaScript code. You can verify this by experimenting with the Member List or Statement Completion feature in the JavaScript file.

image

Fig 3: Adding reference to the C++ WinRT Component DLL.
Add the HTML markup that invokes JavaScript.

Add the following HTML into the <body> node of the default.html page

<body>
    <button id="callwinrt" onclick="CallWinRT()">Call WinRT</button>
<p></p>
    <label id ="Label1" style="background-color: grey;">Activation Object Result ->  </label><label id ="loaded" style="background-color: #51B65A;"></label>
    <p></p>
     <label id ="Label2" style="background-color: grey;">Calling Employee::SayHello() method     </label><label id ="callmethod" style="background-color: #51B65A;"></label>
    <p></p>
     <label id ="Label3" style="background-color: grey;" >Getting  Employee.Name Property value    </label><label id ="retrievedproperty" style="background-color: #51B65A;"></label>
    <p></p>

</body>

 

The default.html page appears as following.

Code Snippet
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>WinWebApp1</title>
    <!– WinJS references –>
    <link rel="stylesheet" href="/winjs/css/ui-dark.css" />
    <script src="/winjs/js/base.js"></script>
    <script src="/winjs/js/wwaapp.js"></script>
    <!– WinWebApp1 references –>
    <link rel="stylesheet" href="/css/default.css" />
    <script src="/js/default.js"></script>
</head>
<body>
    <button id="callwinrt" onclick="CallWinRT()">Call WinRT</button>
<p></p>
    <label id ="Label1" style="background-color: grey;">Activation Object Result ->  </label><label id ="loaded" style="background-color: #51B65A;"></label>
    <p></p>
     <label id ="Label2" style="background-color: grey;">Calling Employee::SayHello() method     </label><label id ="callmethod" style="background-color: #51B65A;"></label>
    <p></p>
     <label id ="Label3" style="background-color: grey;" >Getting  Employee.Name Property value    </label><label id ="retrievedproperty" style="background-color: #51B65A;"></label>
    <p></p>

</body>
</html>

 

Add the JavaScript event handlers that call into the component DLL

Add the following function CallWinRT() at the end of the default.js file. This function is called when you click the button “Call WinRT” on the main page. Notice how JavaScript activates the C++ class, and then calls its methods and populates the HTML labels with the return values.

function CallWinRT() {
    // activate the native Windows Runtime component
    var nativeObject = new CppWinRTComponentDll.Employee();
    document.getElementById(‘loaded’).innerHTML = nativeObject;

    //call a method
    var num = nativeObject.sayHello();
    document.getElementById(‘callmethod’).innerHTML = num;

    nativeObject.name = "Kishore Babu";

    // get the value of the string property
    var propValue = nativeObject.name;
    document.getElementById(‘retrievedproperty’).innerHTML = propValue;
}

 

The complete code of default.js file is as follows.

Code Snippet
(function () {
    ‘use strict’;
    // Uncomment the following line to enable first chance exceptions.
    // Debug.enableFirstChanceException(true);

    WinJS.Application.onmainwindowactivated = function (e) {
        if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
            // TODO: startup code here
        }
    }

    WinJS.Application.start();
})();

function CallWinRT() {
    // activate the native Windows Runtime component
    var nativeObject = new CppWinRTComponentDll.Employee();
    document.getElementById(‘loaded’).innerHTML = nativeObject;

    //call a method
    var num = nativeObject.sayHello();
    document.getElementById(‘callmethod’).innerHTML = num;

    nativeObject.name = "Kishore Babu";

    // get the value of the string property
    var propValue = nativeObject.name;
    document.getElementById(‘retrievedproperty’).innerHTML = propValue;
}

 

Build the solution & deploy the application. If you go to start window, you will find an application WinWebApp1. Click on it.

image

Click on call WinRT button. The values from the C++ DLL are returned and set in the JavaScript application as shown in the following figure.

image

When you build a solution that contains a JavaScript project and a Windows Runtime Component DLL project, the JavaScript project files and the compiled DLL are merged into one package, which you can then deploy locally or remotely for testing or submit to the Windows Store. You can also distribute just the component project as an Extension SDK.

Debugging: When you debug a JavaScript solution that has a component DLL, you can set the debugger to enable either stepping through script, or stepping through native code in the component, but not both at the same time. To change the setting, right-click the JavaScript project node in Solution Explorer, then select Properties > Debugging > Debugger Type.

Be sure to select appropriate capabilities in the package designer. For example, if you are attempting to open a file using the Windows Runtime APIs, be sure to select the Document Library Access checkbox in the Capabilities pane of the package designer.

Download the source code here.

As a C++ developer, I find this useful. If you are a C++ developer and new to JavaScript, you sometimes make the mistake of not using the camel-casing in JS. If your JavaScript code does not seem to be recognizing the public properties or methods in the component, make sure that in JavaScript you are using camel-casing. For example, the Platform::String^ SayHello() C++ method must be referenced as sayHello() in JavaScript.

"The task of the leader is to get his people from where they are to where they have not been." — Henry Kissinger

Under the hood Part 4 : C++ WinRT Component DLL & C++ XAML application – WinRT, Windows 8, C++, Metro

Calling WinRT Component from C++

We have developed a C++ WinRT Component DLL & C#.NET application in the post here Under the hood Part 1 : C++ WinRT Component DLL & C#.NET Metro application

we have seen the compiler generated components for making the C# application access the C++ WinRT component here Under the hood Part 2 : C++ WinRT Component DLL & C#.NET Metro application

We have seen the packaging and installation process that happens in the background during building and deploying of the applications here Under the hood Part 3 : WinRT, Windows 8, C++, C#.NET, Metro, WinRT Component DLL

Going further, I created a C++ Metro application and accessed the C++ WinRT Component DLL from this application. The interesting part here is that C++ applications is XAML based. No more .RC and resource.h files in C++ (for metro). In the previous post, we created a WinRT C++ DLL that contains a class calculatorSample. Now let us create  a C++ application to consume the C++ WinRT DLL.

To get started with creating a C++ XAML application, go to Visual Studio 2011 –> Solution Explorer–> New Project –> Go to Installed Templates section –> Visual C++ –>Select Application and name it as CPPApplication1 as shown in the following fig 1.

image

Fig 1: Creating a C++ XAML application.

Right click on the project, click on Add References and the following dialog shown in figure 2 comes up.

image

Fig 2: Reference manager dialog to add references to another components.

Click on Solution section –> Projects and Select  CppWinRTComponentDLL –> click on Add button and click on Close as shown in figure 3.

image

Fig 3: Selecting WinRT CppWinRTComponentDLL.

The CppWinRTComponentDLL reference appears in the References section as shown in the following figure 4.

image

Fig 4: CppWinRTComponentDLL dll appears in the References section.

Goto MainPage.xaml.cpp and include the namespace for CppWinRTComponentDLL

Code Snippet
using namespace CppWinRTComponentDll;

 

Then create an object of calculatorSample on the heap using ref new. In this scenario, ref new  is like cocreateinstance of COM. It’s a smart allocator. we also use ref class to indicate the authoring of a Windows Runtime class . using ^ to represent a “refcounted” pointer in ZW fits quite well

The following code shows how to use the ref new expression to create a new reference-counted Windows Runtime object. Note that you use the ^ (“hat”) symbol instead of the pointer dereference operator (*) when declaring the variable, but that you use the familiar -> operator to access the objects instance members. Note also that you do not call delete explicitly on the object. The object will be destroyed deterministically when the last remaining copy of it goes out of scope. At the lowest level, the object is basically a COM object owned by a smart pointer.

Code Snippet
CalculatorSample^ calcobj = ref new  CalculatorSample();
txtAddResult->Text = calcobj->Add(10,20).ToString();

 

So from the C++ application, we are calling the C++ Windows Runtime Component DLL. This is all native code. C++ calling C++ and everything is ref counted.

Compiler options: /ZW enable WinRT language extensions /AI<dir> add to assembly search path <dir> is the folder where the compiler searches the winmd files /FU<file> forced using assembly/module force the inclusion of the specified winmd file /D "WINAPI_FAMILY=2" set this define to compile against the ModernSDK subset of Win32

Linker options: /APPCONTAINER[:NO] marks the executable as runnable in the appcontainer (only) /WINMD[:{NO|ONLY}] emits a winmd; if “ONLY” is specified, does not emit the executable, but just the winmd /WINMDFILE:filename name of the winmd file to emit /WINMDDELAYSIGN[:NO] /WINMDKEYCONTAINER:name /WINMDKEYFILE:filename used to sign the winmd file

However, in a Metro style app or Windows Runtime component, all the C++ code is native. The /ZW compiler option causes the Component Extensions to be compiled for Windows Runtime. The /cli compiler option causes them to be compiled for C++/CLI. Currently, C++/CLI is not supported for Metro style apps

Code snippet of the complete MainPage class.

Code Snippet
//
// MainPage.xaml.cpp
// Implementation of the MainPage.xaml class.
//

#include "pch.h"
#include "MainPage.xaml.h"

using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Data;
using namespace CPPApplication1;

using namespace CppWinRTComponentDll;

MainPage::MainPage()
{
    InitializeComponent();

      CalculatorSample^ calcobj = ref newCalculatorSample();
    txtAddResult->Text = calcobj->Add(10,20).ToString();

    int result;
    HRESULT hr = calcobj->__cli_Add(20,30,&result);
    txtAddResult->Text = result.ToString();
}

MainPage::~MainPage()
{
}

All Windows Runtime types derive from the universal base class Platform::Object. There is therefore an implicit conversion from any Windows Runtime object to Platform::Object.

Code snippet of the XAML page.

Code Snippet
<UserControl x:Class="CPPApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable="d"
    d:DesignHeight="768" d:DesignWidth="1366">
    
    <Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
        <TextBox x:Name="txtAddResult" HorizontalAlignment="Left" Text="TextBox" VerticalAlignment="Top" Margin="343,90,0,0" Width="212"/>
        <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Calling C++ component Add method from C++ XAML Application" VerticalAlignment="Top" Margin="81,90,0,0" Height="45" Width="258" FontSize="14" FontWeight="Bold"/>

    </Grid>
    
</UserControl>

 

Build the solution and deploy the application. The application output is as follows.image

Configuration settings:

Enable Windows Runtime Extensions enables the runtime extensions throughout the type system which includes the ability to do Boxing. I.e. Boxing to WinRT type system. Every fundamental types and WinRT types are derived from Platform.Object.image

heap-allocated objects with heap semantics:

Calculator^ calc = ref new Calculator(); // Calculator is a ref class from a custom WinRT component

txtResult->Text = calc->Add(10, 20).ToString();

The ^syntax will fire a destructor when the refcount on the object drops to 0, or if you explicitly call delete. (So if you handed the object out it’s not necessarily at the end of your scope)

heap-allocated objects with Stack semantics:

Calculator calc;

txtResult->Text = calc.Add(10, 20).ToString();

Both of those create heap-allocated objects behind the scenes, but the difference is whether you logically have heap semantics vs. stack semantics.

The stack syntax will fire a destructor when the object goes out of scope (or on an exception etc.). This is important when you e.g. handed of the object to another thread or async callback, so there may still be a refcount on it, but you need to get rid of it right away. (E.g. a file handle that needs to be closed otherwise the file is locked). The main advantage is exception-safe deterministic destruction.

PS: Because of the nature of refcounting, it’s a little bit less important with WinRT to have deterministic destruction than with e.g. the /clr and a garbage collected heap (where the point of destruction is virtually random). However, you will find that with async patterns it is common to get into a situation where you’re transfer the ownership of an object from one thread to another (e.g. via a lambda). There is then a race condition between the two threads for releasing the object. This is generally still ok, but if the object represents a file or other exclusive resource it might be critical to perform the destruction at a specific time, rather than relying on the timing between the two threads.

value classes & Ref classes

Int32 x(15); // Compiles and x is initialized and works as expected.

String str("test1"); // Doesn’t compile and compiler complains C3149: ‘Platform::String’ : cannot use this type here without a top-level ‘^’

Int32 is a value class, and String or the custom winRT component are all ref class. They are different.

Differences between C++/CLI and WinRT C++

In terms of the differences like flags are as follows.

Basic types:
/clr: From mscorlib.dll (System::* types)
/ZW: From vccorlib.dll (Platform::* types)

Lifetime management:
/clr: Garbage collected
/ZW: Refcounted

Cycles Broken:
/clr: By garbage collector
/ZW: Broken by user (weak references or explicit delete)

Code generation:
/clr: MSIL + native code. Can create a cross-platform binary if MSIL-only.
/ZW: Native code only. Binaries target a specific platform.

Object Creation:
/clr: gcnew
/ZW: ref new

interior_ptr:
/clr: Supported
/ZW: Not supported

pin_ptr:
/clr: Supported
/ZW: Not supported

V% (% when it refers to a byref (kind’a like an "interior_ref") ):
/clr: Supported
/ZW: Not supported

R% (% when it refers to an implicitly dereferenced ref type):
/clr: Supported
/ZW: Supported

Ref to ^:
/clr: R^%
/ZW: R^&

Boxing:
/clr: syntax V^
/ZW: IReference<V>^

Dereferenced box type:
/clr: V%
/ZW: const V

Generics:
/clr: Generics classes, interfaces & delegates allowed.
/ZW: Generic interfaces & delegates only.

Static constructors:
/clr: Supported
/ZW: Not supported

Address of member of ref class:
/clr: Returns an interior_ptr
/ZW: Returns a type*

friends:
/clr: Not supported
/ZW: Supported

C++ class embedded in ref class:
/clr: Not supported
/ZW: Supported

ref class embedded in C++ class:
/clr: Not supported
/ZW: Supported (R-on-stack)

^ embedded in C++ class:
/clr: Not supported (Needs GCHandle)
/ZW: Supported

^ embedded in value class with value class on native heap:
/clr: Not supported
/ZW: Supported (for String^)

Global ^:
/clr: Not supported
/ZW: Supported

Global R-on-stack:
/clr: Not supported
/ZW: Supported

Finalizer:
/clr: Supported
/ZW: Not supported

Destructor:
/ZW: Runs on IDisposable::Dispose (delete / stack unwind) only
/clr: Runs on IDisposable::Dispose (delete / stack unwind) -or- last release (never both)

T::typeid:
/clr: Supported
/ZW: Not supported

R-on-stack (ref class on stack) syntax is supported on C++/cli and C++/CX, but you’ll notice that unfortunately the /CX implementation in the developer preview release has a code generation bug that will make it impractical to test this right now. (R^ and R% should be fine though). The most important reason for R-on-stack is exception-safe destruction (Like ‘using’ gives you in C#) – other than that it is purely compiler syntactic sugar.

Download the source code here.

"If one advances confidently in the direction of his dreams, and endeavors to live the life which he has imagined, he will meet with success unexpected in common hours." — Henry David Thoreau

Under the hood Part 3 : Internals of how the application is installed and run – WinRT, Windows 8, C++, C#.NET, Metro

Under the hood Part 3 : WinRT, Windows 8, C++, C#.NET, Metro, WinRT Component DLL

We have developed a C++ WinRT Component DLL & C#.NET application in the post here Under the hood Part 1 : C++ WinRT Component DLL & C#.NET Metro application

we have seen the compiler generated components for making the C# application access the C++ WinRT component here Under the hood Part 2 : C++ WinRT Component DLL & C#.NET Metro application

See the post on First Look at What’s New in Windows 8 here.

Going further, I created a C++ Metro application and accessed the C++ WinRT Component DLL from this application. The interesting part here is that C++ applications is XAML based. No more .RC and resource.h files in C++ (for metro). We will explore the C++ application in another post. In this post, let us walk through the packaging and installation process that happens in the background during building and deploying of the applications.

Basically, there are two registrations for our application.

  1. Extension registration
  2. Class registration.

The figure 1 (from Build con) shows the relation between the two.

image

Fig : Slide related to Extension Catalog and Class Catalog shown @ Build con.

Go to  Visual Studio 2011 –> Solution Explorer –> CSharpApplication project, here you can find a file named Package.appxmanifest as shown in figure 1 . This file has most of the information needed to deploy the application. This is the information that windows uses to identify the application. Package Name is the name used in most of the identification process.

image

Fig 1: Package.appxmanifest file in Visual Studio 2011 Solution Explorer.

Code snippet of Package.appxmanifest file.

Code Snippet
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
  <Identity Name="CSharpApplicationCallingCPPComponent" Publisher="CN=Kishore" Version="1.0.0.0" />
  <Properties>
    <DisplayName>CSharpApplication</DisplayName>
    <PublisherDisplayName>Kishore</PublisherDisplayName>
    <Logo>Images\StoreLogo.png</Logo>
    <Description>CSharpApplication</Description>
  </Properties>
  <Prerequisites>
    <OSMinVersion>6.2</OSMinVersion>
    <OSMaxVersionTested>6.2</OSMaxVersionTested>
  </Prerequisites>
  <Resources>
    <Resource Language="en-us" />
  </Resources>
  <Applications>
    <Application Id="App" Executable="csharpapplication.exe" EntryPoint="CSharpApplication.App">
      <VisualElements DisplayName="CSharpApplication" Logo="Images\Logo.png" SmallLogo="Images\SmallLogo.png" Description="CSharpApplication" ForegroundText="light" BackgroundColor="#222222" InitialRotationPreference="portrait">
        <SplashScreen Image="Images\SplashScreen.png" />
      </VisualElements>
    </Application>
  </Applications>
  <Capabilities>
    <Capability Name="internetClient" />
  </Capabilities>
</Package>

 

The applications implement contract like search contract, share, play queue contract. Those contract registrations are the extensions registration for the operating system.  Tile that you see in the Windows start page is just another contract activation. I,e windows.launch contract. So if you go to HKEY_CURRENT_USER\Software\Classes\Extensions\ContractId\Windows.Launch, you can find your application package id that we saw in figure 1. Everything under Windows.Launch is organized by package ID as shown in the figure 2 below.

image

Fig 2: Registry settings showing the registered Extensions.

From figure 2, we can see our package HKEY_CURRENT_USER\Software\Classes\Extensions\ContractId\Windows.Launch\ PackageId\csharpapplicationcallingcppcomponent_1.0.0.0_x86_neutral_kb63pw67p0swp. This package has a  ActivatableClassId key . Under that we see App as shown in figure 3. This is the class registration for this extension. image

Fig 3: App registry settings for your application.

Let us see how the class registration for the applications looks like. First, We have extensions which say I implement this contract for ex I implement this launch and then we have classes. The extensions point to the classes. classes are actually the implementation. All applications are just Windows Runtime objects to the Windows OS, this is where all it starts. This is the windows runtime class that the OS knows about for your application.

The interesting part is in the class registration for the application. If we go up in the registry editor, we should see a registry key called ActivatableClasses at  HKEY_CURRENT_USER\Software\Classes\ActivatableClasses, this is where the class registrations are for all of our applications are. Here again we find package. All extensions, all classes are organized based on the package. That means our application or package has unique set of classes and they don’t share extension points or classes with other applications. They are all unique for our app. If we expand it, we see ActivatableClassId, the same name we saw in extensions. Here we should find the App classId. This is the WinRT class registration. This is the same for all types of applications, libraries etc.

Here we can see some registration attributes . The ActivationType is an important one. Windows Runtime supports two activation styles.

  1. InProcess activation
  2. Out of process activation

So Windows Runtime supports InProcess activation where we provide the DLL and windows load that into the process and it also supports out of process activation, where we will provide an exe and windows will launch the exe as your class implementation.

Registry key values:

ActivationType = 1 indicates its out of process activation class. out of process classes have a server. we have to know where the executable is, so there is a server registion here.

ActivationType = 0 indicates its in process activation

Out of process has a server and so there is a server registration here. Server with value App.AppXpdnr4x0evrk1yjmz5xfw2ksncfcjc5er.mca as shown in figure 4.image

Fig 4: Server registry values for your application.

In figure 3, below the ActivationType , we can find Server attribute and it contains the App.AppXpdnr4x0evrk1yjmz5xfw2ksncfcjc5er.mca we got from the above Server value.  The server registration, tells the windows runtime enough information about what code we actually need to get from the disk and start running to get the app up and running. The ExePath attribute gives the path to the exe.

Windows runtime supports two apartment models. MTA & STA. If you have worked in VC++ COM, COM+ earlier, then you might have programmed the components for Multi Threaded Apartment model & Single Threaded Apartment model.

Let us see some more ActivatableClassId entries for Windows Runtime present at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsRuntime as shown in figure 5.

image

Fig 5: Windows Runtime classes information.

Finally, the slide that caught my attention was the deployment pipeline process shown in Fig 6 that shows the overall view of the above mentioned information.

image

Figure 6 showing the role of the deployment engine @ Build Con.

"Only those who risk going too far can possibly find out how far they can go." – T.S. Eliot

Under the hood Part 2 : C++ WinRT Component DLL & C#.NET Metro application

We have developed a C++ WinRT Component DLL & C#.NET application in the post here Under the hood Part 1 : C++ WinRT Component DLL & C#.NET Metro application

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.

Code Snippet
#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

Fig 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

Fig 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 a 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

Fig 3: Interface ICalculatorSamplePublicNonVirtuals created by the compiler

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

Fig 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.

Code Snippet
.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 to 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 for 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.