Monthly Archives: May 2012

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

Advertisements

Mobile Is Where The Future Is

All of this is good news for entrepreneurs since they are in the best position to take advantage of all of these changing dynamics. It is not as good news for those who find themselves operating a big Internet business started more than five years ago. You are going to need to make a hard right turn super fast without flipping over the car.

In the past fifteen years, we have seen Microsoft go from being an unstoppable force to being a non-factor in many important new markets, we have seen Google go from being an unstoppable force to being a non-factor in many important new markets, and I suspect we are going to see Facebook struggle with the same thing. RIM is dying quickly now. Yahoo! is a question mark.

In technology the more things change, the more the stay the same. You cannot ever rest. Because the big change that is going to upset your nice apple cart is right around the corner. Today that is mobile. Tomorrow, who knows? I am trying like hell to figure out what that will be and jump on it. Because that’s how you play this game.

If you look at any of the top web properties on comScore, Quantcast, Alexa or any other third party reporting service you will see that they all have been fairly flat over the first half of the year. You might think that all these big web services are flatlining.

We have seen this in our portfolio too. From board meeting to board meeting, we are seeing a similar pattern. Web is flattish. But mobile is growing like a weed.

Mobile does not reward feature richness. It rewards small, application specific, feature light services. I have said this before but I will say it again. The phone is the equivalent of the web application and the mobile apps you have on your home screen(s) are the features.

User experience is not the only big change/challenge for companies trying to navigate this transition. Monetization is different too.

82 Percent of Time Spent with Mobile Media Happens Via Apps: http://www.comscore.com/Press_Events/Press_Releases/2012/5/Introducing_Mobile_Metrix_2_Insight_into_Mobile_Behavior/

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.