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. Part 2 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
Part 5 discusses developing JavaScript application that consumes WinRT Component DLL
Let's 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.
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 the Add()
method causes the compiler to create an inline native to COM wrapper method. Also, on the left hand side, COM HRESULT
s 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)
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 HRESULT
s 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 HRESULT
s (such as S_FALSE
) that need to be checked explicitly by the caller.
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.
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 it's 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:
#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();
int result;
HRESULT hr = calcobj->__cli_Add(10,20,&result);
txtAddResult->Text = result.ToString();
}
Another (3rd) way is to use function pointers and call the methods using pointers. Basically, 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();
int result;
typedef HRESULT (__stdcall* AddFunc_t) (CalculatorSample^ calc, int i, int j, int * result);
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
.
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 three 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.
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:
#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();
int result;
typedef HRESULT (__stdcall* AddFunc_t) (CalculatorSample^ calc, int i, int j, int * result);
AddFunc_t* addFunc = *reinterpret_cast<AddFunc_t**>(calcobj);
addFunc[6](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."