Building and using C++ WinRT components
Written by Mike James   
Monday, 10 October 2011
Article Index
Building and using C++ WinRT components
Using the CX componenent

 

Using the component from VB

To use the component from VB .NET you have to go through the same steps. First you have to add a reference to the object select Add Reference, next click Browse and navigate to the Debug directory of the MyWinRTComp project and select the MyWinRTComp.winmd file.

You also have to add a reference due to a glitch in the pre-beta software platform.winmd that you will find in C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\.

You can also add

Imports MyWinRTComp

to the start of the program to avoid having to quote fully qualified names.

Once this is done you can use the component as if it was a standard Basic object. First create an instance:

Dim MyObject As New WinRTComponent

Again this creates a COM object behind the scenes. You can use its properties, methods and events as if it was a standard VB object:

MyObject.PropertyA = 1
Dim temp As Integer = MyObject.PropertyA
temp = MyObject.Method(1)
AddHandler MyObject.someEvent, AddressOf Myhandler

Using the component from JavaScript

All you have to do to make use of the component from JavaScript is, once again, load a reference. Right click on References in the Solution explorer and brows to the Debug directory of the MyWinRTComp project and select the MyWinRTComp.winmd file. After this the WinRT component looks just like a standard JavaScript object. However there are some slight differences from the way it all works in the other languages. The first is that there is no JavaScript equivalent of "using" or "import" - you have to use a fully qualified name. For example to create an instance of the object you have to use:

var MyObject = 
new MyWinRTComp.WinRTComponent();

The second difference is the JavaScript enforces a "camel case" style on method and properties. That is even if you have created a method with the name MethodOne it will be changed to methodOne i.e the first character is always lower case. With this difference taken into account everything works in the same way:

var temp = MyObject.propertyA;
temp = MyObject.method(1);
MyObject.someEvent = function EventHandler(){};

Except at the moment it doesn't actually work. In the current build you get an error when you try to create the object. It does work if you add the WinRT component project to the solution and add the reference directly. Presumably this is a short lived bug that will be fixed in the next release.

 

Using the component in C++

Interestingly using the component from C++ is probably the most difficult thing to do with the current state of the software - ignore the lack of Intellisense prompting and even some initial error messages.

First to use the component you have to add a reference. Right click on the projects name and select References. When the dialog box appears select Add New Reference and navigate to  the Debug directory of the MyWinRTComp project and select the MyWinRTComp.winmd file. You can also add

using namespace MyWinRTComp;

if you want to avoid typing fully qualified names.

Once you have done this, there is no need to add a reference to platform.winmd in this case you can start to use the component. First we need to instantiate an object:

WinRTComponent^ MyObject =
ref new WinRTComponent();

Notice the use of ^ and ref new to create a reference and a new COM object.

Once we have the reference to the COM object it can be used, with some slight modifications, as if it was a native object. For example:

MyObject->PropertyA=1;
int temp=MyObject->PropertyA;
temp=MyObject->Method(1);
MyObject->someEvent +=
ref new SomeEventHandler( [](int i){});

The only slightly strange instruction is the use of the lambda to set the event handler. The Lambda is simply

[](int i){};

which defines a dummy i.e. empty function with the signature (int) returning void.

Lambdas were introduced recently but you can't use them with managed code i.e. they are not managed code lambdas but this isn't managed code - ignore any error messages as it does work with COM objects.

Under the hood

The most important thing to realize is that you don't need to know any of the inner workings of the WinRT component to make use of it.

WinRT objects are COM objects but their primary interface is IInspectable rather than IUnknown - however IInspetable inherits from IUnknown so you really do have a COM object to work with.

WinRT objects are created by an activation factory rather than an object factory. An activation factory has to implement the IActivationFactory interface and the compiler generates one for you automatically. You can use a range of low level functions and templates that have been included in WinRT but it is probably better to leave the compiler to do the job.  It also uses QueryInterface to retrieve the interface it needs and AddRef and Release to enable the use count to be maintained. The compiler automatically generates the _IWinRTComponentPublicNonVirtuals interface to provide access to your custom methods.

For most of the time you can ignore the fact that you are working with COM but there is one small place where the mechanism breaks the surface. You can use whatever data types you like in the internal workings of your component but data types that are going to be placed in the public interface used to call your object have to be COM datatypes.  In many cases the data types are the same but where there is a need new COM data types have been introduced in WinRT. For example, the COM and C++ native string data type are different. If you need to use a string as a return type, parameter or property then it has to be a  WinRT string i.e. Platform::String:

Platform::String^ MyString="Hello World";

and there are conversion methods to and from standard C++ strings. For example

std::MyStdString=MyString->Date();

and

Platform::String^ MyCOMString=
ref new Platform::String(
MyStdString.c_str());

As well as simple COM types, WinRT also has COM equivalents of more complex data structures, such as collections. This juggling of data types is about the only real complication in creating a WinRT component.

Yes, this really is COM and the point is that when you instantiate a WinRT object a lot goes on behind the scenes. For the most part this is best where it stays!



Last Updated ( Friday, 14 October 2011 )