Qt’s WinRT port and its C++/CX usage

Published Friday April 19th, 2013 | by

Background

After Friedemann has given an initial introduction about Qt’s Windows Runtime port, I would like to give some further insight about technical aspects and our ways of working on the port.

When reading about Windows Runtime development (Windows 8 store applications and Windows runtime components) in connection with C++ you will find C++/CX again and again. Windows C++/CX are C++ language extensions which were developed by Microsoft to make software development for Windows Runtime easier by bringing it “as close as possible to modern C++” (Visual C++ Language Reference (C++/CX)). In some cases, these extensions look similar to C++/CLI constructs, but they might have other meanings or slightly different grammar.

The first thing that catches someone’s eye when one has a look at C++/CX documentation or an example/application are lines like
Foo ^foo = ref new Foo();
The ^ is basically a pointer, but gives the additional information that it is used on a ref-counted COM object so that memory management happens “automagically”. The “ref new” keyword means that the user wants to create a new “Ref class” (see Ref classes and structs in Type System (C++/CX)), which means that it is copied by reference and memory management happens by reference count.  So there isn’t much magic involved in that line; it only tells the compiler that the object’s memory can be managed by reference count and the user does not have to delete it himself.

Basically C++/CX is just what its name tells us it is – extensions to the C++ language. Everything ends up as native unmanaged code quite similar to the way Qt works. Some people might argue whether it is necessary to reinvent the wheel for the n-th time where a lot of the “problems” are actually solved in C++11 (by the way, auto foo also works in the example above), but that is what was decided for Windows Runtime development.

Use of C++/CX inside Qt’s WinRT port

Microsoft has said on different occasions (among others during the Build conference 2012) that everything that can be done using C++/CX can also be done without the extensions, as everything ends up as native code in either case. So we had to decide whether we want to use the new fancy stuff or take the cumbersome road of manual memory management etc. Theoretically there is nothing that keeps us from using C++/CX in Qt’s WinRT port, but there are some reasons why we try to avoid them.

For one, these extensions might prevent developers who are willing to help with the Windows Runtime port from having a deeper look at the code. If you do not have any previous experience with this development environment, having new constructs and keywords (in addition to new code) might be enough for you to close the editor right away. While WinRT code which doesn’t use CX might not be especially beautiful, there are no non-default things which might obscure it even more.

Another issue is that Qt Creator’s code model cannot handle these extensions (yet). You don’t get any auto completion for ^-pointers, for example. This can of course be fixed in Qt Creator and time will tell whether it will be, but at the moment the port and basic Qt Creator integration (building, debugging & deployment) are our first priorities.
Due to these facts, we decided that we do not want to use the extensions. Though, if someone wants to help out with the port and is eager to use CX he/she might be able to persuade us to get the code in (after proper review of course ;) ).

Problems and challenges of not using C++/CX

The main problem when it comes to development of Windows Runtime code without using C++/CX is the severe lack of documentation. While the MSDN documentation generally can be improved in certain areas, it almost completely lacks anything about this topic. But thanks to Andrew Knight, who gave me an initial overview how things are to be used and was always helpful whenever I had additional questions, I think I am getting the grip on things. In order to help others who want to join the efforts (and have all the things written down), I will cover some basic areas below.

Namespaces

The namespaces given in the documentation are always the same for the CX usage of the classes,  just with “ABI” added as the root namespace. So for StreamSocket, Windows::Networking::Sockets becomes ABI::Windows::Networking::Sockets. Additionally, you probably need Microsoft::WRL (and also Microsoft::WRL::Wrappers). WRL stands for “Windows Runtime C++ Template Library” and is used for direct COM access in Windows Runtime applications – but you will also need its functionality when omitting CX (for creating instances for example).

Creating instances

When not using CX, most of the classes cannot be accessed directly. Instead, there are interface classes which need to be used. These interfaces are marked by an ‘I’ in front of the class name so that StreamSocket becomes IStreamSocket. As these interfaces are abstract classes, they cannot be instantiated directly. First of all, you have to create a string which represents the class’s classId.
HStringReference classId(RuntimeClass_Windows_Networking_Sockets_StreamSockets);

These RuntimeClass_Windows… constructs are defined in the related header files and expand to strings like “Windows.Networking.Sockets.StreamSocket” for example. The way objects can be instantiated depends on whether the class is default constructable or not. If it is, ActivateInstance can be used to obtain an object of the type you are after.

IStreamSocket *streamSocket = 0;
if (FAILED(ActivateInstance(classId.Get(), &streamSocket)) {
// handle error
}

Unfortunately, the ActivateInstance convenience function fails for StreamSocket in that case as it expects a ComPtr as parameter. In order to avoid that failure one has to take the long way using RoActivateInstance

IInspectable *inspectable = 0;
if (FAILED(RoActivateInstance(classId.Get(), &inspectable)) {
// handle error
}
if (FAILED(inspectable->QueryInterface(IID_PPV_ARGS(&streamSocket)))) {
// handle error
}

If the class is not default constructable, it has to use a factory in order to create instances. These factories can be obtained by calling GetActivationFactory with the appropriate class Id. One example of a class like that would be HostName:

IHostNameFactory *hostnameFactory;
HStringReference classId(RuntimeClass_Windows_Networking_HostName);
if (FAILED(GetActivationFactory(classId.Get(), &hostnameFactory))) {
// handle error
}
IHostName *host;
HStringReference hostNameRef(L"http://qt-project.org");
hostnameFactory->CreateHostName(hostNameRef.Get(), &host);
hostnameFactory->Release();

People who are used to Windows development probably have already noticed that all this is COM based. That means that all this has been around for ages and is loved everywhere.

Calling static functions

For classes which have static functions there is an extra interface for these functions. These interfaces are marked by “Statics” at the end of the “basic” interface name and can also be obtained by using GetActivationFactory. One example would be IDatagramSocketStatics which contains GetEndpointPairsAsync for example.

IDatagramSocketStatics *datagramSocketStatics;
GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics);


IAsyncOperation<IVectorView *> *endpointpairoperation;
HSTRING service;
WindowsCreateString(L"0", 1, &service);
datagramSocketStatics->GetEndpointPairsAsync(host, service, &endpointpairoperation);
datagramSocketStatics->Release();
host->Release();

The endpointpairoperation defines the callback(s) for this asynchronous function, but that topic could be covered in another post. The interesting parts here are how the datagramSocketStatics pointer is filled by calling GetActivationFactory and the actual call to the static function by datagramSocketStatics->GetEndpointPairsAsync(...).

ComPtr

There is a way to use reference counted memory management even without using CX. It can be achieved by using the Microsoft-provided smart pointer ComPtr. So
IStreamSocket *streamSocket
would become
ComPtr<IStreamSocket> streamSocket.
When using these, we had some memory access errors we could not explain (but did not investigate much further). In addition to that, Qt Creator does not support code completion with “streamSocket->” but one would have to call “streamSocket.Get()->”. Thus we decided not to use ComPtr but keep using “normal” pointers. All you have to do is to remember to call “Release” as soon as you are done with the pointer.

All in all, we try to avoid these extensions even though it might not make the code beautiful. If you want to contribute though and feel at home using these, feel free to create a patch containing CX code. If you have any further questions or advice, feel free to add them in the comments or join us in #qt-winrt on freenode.

Did you like this? Share it:

Posted in Background, Qt, Windows

50 comments to Qt’s WinRT port and its C++/CX usage

Ionut Dediu says:

OMG, what have they done to C/C++ ?!?!

I believe if I am ever going to return to Windows programming I will stick with Win32 C APIs.

I once tried to port a small GUI app from Win32 to a more modern .NET UI and started looking into C++/CLI. I was totally horrified of the syntax and the new paradigms.

So thanks Qt for giving me a clean and elegant C++ wrapper for Windows programming and hiding all these “improved” extensions from me.

M.S. Babaei says:

I’ve just felt the same.

danny says:

I was surprised at first by how many Windows-only applications are written in Qt. Now I know why.

tr3w says:

I think not using the C++/CX was a good decision.

On the other hand, not using RAII/smart pointers/ComPtr is two steps backwards.
The first thing you will forget is to call Release() in every code path. It is exactly the same problem what we have with new and delete.

gigaplex says:

I agree. I’m assuming the reason code completion doesn’t work on the ComPtr class is the overloaded -> operator returning a hacked pointer cast to hide AddRef/Release, Qt could just roll their own that doesn’t do that.

David says:

I think not using the C++/CX was a good decision.

On the other hand, not using RAII/smart pointers/ComPtr is two steps backwards.
The first thing you will forget is to call Release() in every code path. It is exactly the same problem what we have with new and delete.

+1

Very, very, +1

Kuba Ober says:

Agreed. Not using ComPtr is just as silly as not using other C++ pointer types, such as QScopedPointer etc.

nogden says:

Why not std::unique_ptr / std::shared_ptr with a custom deleter that calls Object::Release() on destruction? Just std::bind() the instance to the Release() member, store it in a std::function and wrap the whole thing in a nice qt::make_com() wrapper. That way you can have all the benefits of reference counting with non of the silly language extensions.

tr3w says:

That would be slow, and memory hungry, but yes, one can create a QComPtr easily if she/he has problems with ComPtr.

danny says:

“That would be slow, and memory hungry”

Why? This isn’t garbage collection. The only cost is the reference count which is negligible next to the guarantee that resources are properly cleaned up.

tr3w says:

The std::bind creates an unnecessary object on the heap, the std::function will create another one.
It’s at least two new, and two indirection. Totally fine when we need one quick solution for one place, not so good when we want to use it million times.

Also the COM objects have an internal reference count mechanism (AddRef()/Release()) so no need to use another one.

Ionut Dediu says:

If we want reference counting/ComPtr/all that modern garbage (collection) we might as well use Java/.NET and be done (with Qt).

gigaplex says:

Java/.NET don’t use reference counting, and reference counting is not garbage collection. It’s a deterministic lifetime model.

Qt already uses reference counting, a prime example is the QSharedPointer class.

tr3w says:

And QVector, QString… http://qt-project.org/doc/qt-4.8/implicit-sharing.html#list-of-classes

danny says:

That’s implicit sharing, not quite the same thing.

tr3w says:

It’s reference counting with Copy-On-Write semantics.

danny says:

C++ is complex enough without yet another proprietary extension to the language.

And how someone at MS thought ‘^’ would naturally mean ‘reference counted pointer’ is beyond me!

We’ve had reference counting in C and C++ for decades and it didn’t require extensions to the base language. Instead of ‘^’ they should have used ‘EEE’ for Embrace, Extend, Extinguish;

C++/CX needs to die.

Kuba Ober says:

It’s just as “natural” as “*” meaning “a pointer”. It’s a matter of convention. ^ should be familiar to those who dealt with Pascal, ref rings a bell to Algolites. Speaking many languages sometimes widens your horizons and makes you less surprised at stuff :)

Henry Skoglund says:

“… has been around for ages and is loved everywhere…”

You almost made me spill coffee on my Retina keyboard with that sentence :-)

MrVariable says:

Your C++ notation sucks btw… the variable is a pointer to IStreamSocket, so you should write IStreamSocket* streamSocket = 0;
instead of IStreamSocket *streamSocket = 0; even though the compiler accepts both.

Lilian says:

Read on “Coding Conventions” for C++.
As a first start, here is for Qt: http://qt-project.org/wiki/Qt_Coding_Style

Will says:

If you have two things on one line, the placement of the * can have a big impact on readability:
IStreamSocket* foo, bar; looks like foo and bar will be the same type at a glance. But, the * only applies to foo. So, a lot of people consider it good practice to always put the * with the name instead of the type.

danny says:

Or don’t declare multiple variables on the same line. Then it’s a non-issue.

lacosaes0 says:

That means that all this has been around for ages and is loved everywhere.

LOL no.

Marat Abrarov says:

Thus we decided not to use ComPtr but keep using “normal” pointers.
Step backward :( It’s better to write QComPtr for Qt.
Please, don’t use raw pointers in 2013 (C++11 is already here)! Especially with COM/OLE (I personally like to use “Compiler COM Support Classes” with MSVC: _com_ptr_t, _bstr_t, etc).

terry says:

Wrapped those raw pointer by unique_ptr or just design a lightweight wrapper for them, it should not be too hard.But even in 2013, you could find c++ programmers with years experience refuse to rely on RAII, they keep telling me RAII is expensive blahblahblah, even after you show them the truth RAII is not as expensive as they though, that depend on what kind of smart pointer you are using, they keep telling you “abstraction will bite you one day, if you want safe codes, you should write bare bone codes, they are faster, safer, and easier to debug”. No way to change them, even c++11 is out, I still feel pessimistic about c++.

Marat Abrarov says:

Wrapped those raw pointer by unique_ptr or just design a lightweight wrapper for them, it should not be too hard.

Of course, I’ll do so. But it’s better to Qt provides them in its code/interfaces/classes/etc by default.

Rovshan says:

Ms keeps inventing new totally useless things to earn money on it and to discontinue after several releases and start some new totally useless thing. So you need to keep learning technologies that will be discontinued soon instead of adding up to your knowledge and doing something real with it. Now they started to play with C/C++.

Lilian says:

There is no need to use raw pointers if you don’t want to.
There is: QSharedPointer, QScopedPointer… shared_ptr…
And now in C++14: make_unique and make_shared

Zeke says:

Why don’t we just create bindings of Qt for C#?

gigaplex says:

Creating .NET bindings for a heavily C++ API is hard. Also, WinRT is natively C++ and some stuff can’t be done entirely in C# yet so why would Qt go there?

Ian Monroe says:

Yep, seems like Windows 8 really backs away from MSFT’s commitment to .NET. So we shouldn’t complain about C++/CX too much I don’t think. :)

Actually there already are free and open source (LGPL) C#-bindings for Qt, check them out at http://techbase.kde.org/Development/Languages/Qyoto. They wrap just Qt 4 for now but I’ve been already working for a week now on Qt 5 support, it will be complete in a month at most.

Mikael Lindgren says:

Please have a look at an old library called comet (http://www.lambdasoft.dk/comet/)
It wraps COM into a very nice set of c++ classes allowing you to use plain c++ to access COM object. Much nicer and easier to use than any Microsoft implementation.

COM errors are automatically translated to exptions, and vice versa. Just to mention one of the nice features.

A more comprehensive feature list at: http://www.lambdasoft.dk/comet/features.htm

David says:

@Mikael

I don’t know too much about COM, but that comet library looks nice. It’s also liberally licensed.

Could this help the WinRT Qt port?

Mikael Lindgren says:

I believe so. You run a utility called tlb2h on any COM type library, and get a header file with all COM classes and interfaces wrapped into a set of easy to use c++ classes

Tomas says:

I don’t think this will work. WinRT comes with “newer version” of COM which differs from the old COM in several areas. For example component activation is different – you don’t registry your component in registry anymore. There is now COM inheritance and static function members (emulated by normal members in object factories). If comet didn’t get significant update there is a small chance it will just work.

smoggy says:

Just say no to MSFT proprietary bullshit.

David says:

On the other hand, WinRT is a proprietary Windows platform.

What’s wrong with using that platform’s native (and proprietary) tooling to create the Qt port? Seems odd _not_ to do that.

Pablo Rogina says:

Great decison not to embrace this new (and totally unnecessary) C++/CX that Microsoft invented for some obscure reasons…

Pablo Rogina says:

Great decision not to embrace this new (and totally unnecessary) C++/CX that Microsoft invented for some obscure reasons…

[...] the 17th five two two-time all involved. [...]

lolo says:

ÇHonestly, and I think I speak for the majority of users: we’re not interestered in Win8 and WinRT is a total fiasco. Better use your time in other things.

Henry Skoglund says:

Indeed, if the rumor is true that Win8.1 a.k.a. Blue (to be released this summer) will allow booting into a classic desktop, that will be the first nail in WinRT’s coffin, I believe.

Please note that a WinRT does have to a very large extent the same codebase to enable Windows Phone support. Meaning with the Qt/WinRT version we are aiming at both those distribution platforms.

[...] to be complete for Qt 5.2 coming out before the end of this year. We are also working with the WinRT port of Qt to be available soon after Android and iOS. With the introduction of support in Qt 5.1 for the [...]

Keep up the very good work.

JB says:

Ironic really how many comments there are here complaining about non standard extensions to c++.
Qt signals and slots anyone?

This is why I don;t use either C++/CX or Qt. Neither of them are c++

terry says:

Many people do not complain about the signal and slot of Qt because it is very easy to use and learn,
clean and concise, they make the codes become easier to manage(The only draw back for me is unable to
work with template). Extension of the langauges are not a bad thing, but something extremely awkward like
microsoft did is another story, I would drop back to C API rather than using those unfriendly API designed by
microsoft.

danny says:

Except Qt signals and slots are NOT an extension of the language itself – they’re macros that are picked up by the MOC compiler that then spits out standard C++ in a accompanying header.

Qt signals and slots filled a major hole in C++98: the inability to easily bind arbitrarily member function callbacks to signals.

Any conforming C++ compiler can build Qt and Qt apps but only Visual Studio can build C++/cx.

This ‘^’ bullshit is just Microsoft’s latest attempt to lock developers into it’s platform.

Commenting closed.