Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Using WinRT/CPP with QT 6.x.x.
Forum Update on Monday, May 27th 2025

Using WinRT/CPP with QT 6.x.x.

Scheduled Pinned Locked Moved Solved General and Desktop
14 Posts 3 Posters 2.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H hskoglund
    2 May 2022, 19:12

    Hi, forgot to mention, in the Application Output in Qt Creator, before the Qt Forum post titles appear, you'll see this infamous line:
    QWindowsContext: OleInitialize() failed: "COM error 0xffffffff80010106 RPC_E_CHANGED_MODE (Unknown error 0x080010106)

    This is a harmless warning (Qt Python users know it quite well I believe) due to WinRT/CPP and Qt fighting over who owns COM. I haven;t solved it yet but there are plenty of Google hits on it :-)

    Edit: tested today: found a workaround to the fight over COM: change main.cpp to this:

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        winrt::uninit_apartment();
        winrt::init_apartment();
    
        MainWindow w;
        w.show();
        return a.exec();
    }
    

    Normally if you let QApplication have the first call the COM then WinRT/CPP later crashes, but by first resetting/uniniting WinRT/CPP it seems to make it happy. And no more "... failed: "COM error ... " warning messages :-)

    C Offline
    C Offline
    Chris Kawa
    Lifetime Qt Champion
    wrote on 2 May 2022, 22:26 last edited by
    #4

    @hskoglund The warning is related to COM apartments (sort of a sandboxes in which COM operates). COM should be initialized in each thread it is used in. There are two modes - single and multithreaded. In single threaded mode an apartment is created just for that thread. In multithreaded mode every thread of a process that initializes COM in multithreaded mode shares a common apartment.
    You can initialize COM multiple times on a single thread. The following calls are just refcounted but do nothing else. There's a restriction though that on a single thread COM can only be initialized in one mode at a time (which makes sense).

    The problem here is that for whatever reason Qt initializes COM internally and does so in single threaded mode :( The default mode for winrt init_apartment function is multithreaded and thus you get a warning.

    So the "trick" above just shuts down COM initialized by Qt in single threaded mode and reinitializes it, this time in multithreaded mode.

    If you're ok with single threaded mode you can just skip the winrt::init_apartment() call altogether. Qt already initializes it. You can also explicitly call it as winrt::init_apartment(winrt::apartment_type::single_threaded);, but that's just gonna bump the refcount.

    Having said that, winrt is designed to work asynchronously on multiple threads, so running it in single threaded mode COM is not a good idea and thus the above workaround is needed. It would be nice if Qt exposed that as a setting somehow, but oh well.

    Btw. if you want to be forward looking you should compile your code in C++20 mode and use /await:strict switch variant instead. This is a compiler mode conformant to the coroutines as standardized and will become the default in the future versions of the compiler. You might as well start using it already to avoid rewrites in the future. The /await switch in C++17 mode implements coroutines as they were in the technical spec before standardization, and thus are a legacy non-conformant Microsoft's version.

    1 Reply Last reply
    2
    • A Offline
      A Offline
      alatnet
      wrote on 2 May 2022, 23:11 last edited by
      #5

      Thanks for the help.
      I was able to compile it but apparently i could not used the "/await:strict" compiler switch. Something to do with experimental coroutines? Probably old libraries.

      What I have done is the following:

      CONFIG += c++20
      QMAKE_CXXFLAGS += "/Zc:__cplusplus" "/Zc:twoPhase-"
      DEFINES += _SILENCE_CLANG_COROUTINE_MESSAGE #this is needed as apparently the coroutine include is experimental/unsupported?
      win32:LIBS += -lwindowsapp
      

      Apparently it might be the Qt's intellisense that is stating that there's "no member named 'wait_for' in namespace winrt::impl".

      Now, trying to actually use the functions is not working right...
      Apparently "a function that returns 'auto' cannot be used before it is defined" is happening.

      And trying to use this example, is resulting in a bit of errors...

      I'll see about running some msvc build tools updates...

      1 Reply Last reply
      0
      • C Offline
        C Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on 2 May 2022, 23:35 last edited by Chris Kawa 5 Feb 2022, 23:36
        #6

        I'm on the latest VS2022 and Windows SDK and that example, slightly modified, compiles ok:

        .pro

        QT += core gui widgets
        CONFIG += c++20
        QMAKE_CXXFLAGS += /await:strict
        
        SOURCES += main.cpp
        LIBS += -lwindowsapp
        

        main.cpp

        #include <winrt/Windows.Foundation.Collections.h>
        #include <winrt/Windows.Gaming.Input.h>
        
        using namespace winrt;
        using namespace Windows::Gaming::Input;
        
        int main()
        {
            std::vector<RawGameController> myRawGameControllers;
            for (auto const& rawGameController : RawGameController::RawGameControllers())
            {
                auto it{ std::find(begin(myRawGameControllers), end(myRawGameControllers), rawGameController) };
                if (it == end(myRawGameControllers))
                {
                    myRawGameControllers.push_back(rawGameController);
                }
            }
        }
        

        Note that I'm not using any coroutines here, so the await switch is not necessary in this case.
        Also no devices are found for me, but I think you need to have a winrt window (or any window) for that. For console apps the older XInput api is recommended instead.

        1 Reply Last reply
        1
        • A Offline
          A Offline
          alatnet
          wrote on 2 May 2022, 23:48 last edited by
          #7

          Using VS 2019, though i believe i've updated my libraries...
          Here's the errors:
          Screenshot 2022-05-02 194403.png

          And here's the compilers that im using for MSVC with Qt 6.3.0:
          Screenshot 2022-05-02 194436.png

          I had removed an old sdk (and apparently only installed the win 11 sdk XP) but the win 11 sdk says it's version 10.0.22000.0, gonna install the "latest" win 10 sdk, which it's version is 10.0.20348.0.
          Screenshot 2022-05-02 194748.png

          1 Reply Last reply
          0
          • H Offline
            H Offline
            hskoglund
            wrote on 3 May 2022, 00:03 last edited by
            #8

            Hi Chris, thanks for the explanation of the COM fighting, indeed it would be easier if Qt allowed different COM apartment flavors.

            I also tried that sample, I installed VS2019 16.11.13 and on Windows 10 21H2 Build 19044.1645. I have not installed any special SDK, just Visual Studio and Qt 6.3.0. It copied it the C++/WinRT example verbatim (but I hat to remove that line with "..." :-)
            it compiled cleanly for me, I reused the mainwindow.cpp from my sample above and replaced it with this:

            #include "mainwindow.h"
            #include "ui_mainwindow.h"
            #include "qtimer.h"
            #include "qdebug.h"
            
            #pragma comment(lib, "windowsapp")
            
            #include <winrt/Windows.Foundation.Collections.h>
            #include <concrt.h>
            #include <winrt/Windows.Gaming.Input.h>
            
            using namespace winrt;
            using namespace Windows::Gaming::Input;
            
            MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
            {
                ui->setupUi(this);
            
                std::vector<RawGameController> myRawGameControllers;
                concurrency::critical_section myLock{};
            
                for (auto const& rawGameController : RawGameController::RawGameControllers())
                {
                    // Test whether the raw game controller is already in myRawGameControllers; if it isn't, add it.
                    concurrency::critical_section::scoped_lock lock{ myLock };
                    auto it{ std::find(begin(myRawGameControllers), end(myRawGameControllers), rawGameController) };
            
                    if (it == end(myRawGameControllers))
                    {
                        // This code assumes that you're interested in all raw game controllers.
                        myRawGameControllers.push_back(rawGameController);
                    }
                }
            
                QTimer::singleShot(10,[] { qApp->quit(); });
            
            }
            
            MainWindow::~MainWindow()
            {
                delete ui;
            }
            
            

            So to make it compile. check that you have updated your Visual Studio 2019.
            And also I have no controllers to test with. Perhaps you have any Game Controller stuff or example using a mouse or keyboard we can try?

            1 Reply Last reply
            0
            • H Offline
              H Offline
              hskoglund
              wrote on 3 May 2022, 00:17 last edited by hskoglund 5 Mar 2022, 00:18
              #9

              Hmm, re. MSVC2019 compiler versions, here's my list from within Qt Creator:
              Screenshot 2022-05-03 at 02.17.04.png

              1 Reply Last reply
              0
              • C Offline
                C Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on 3 May 2022, 00:34 last edited by
                #10

                @alatnet Make sure you have #include <winrt/Windows.Foundation.Collections.h>. The example is missing it and that's where the begin/end functions are.

                H 1 Reply Last reply 3 May 2022, 00:41
                0
                • C Chris Kawa
                  3 May 2022, 00:34

                  @alatnet Make sure you have #include <winrt/Windows.Foundation.Collections.h>. The example is missing it and that's where the begin/end functions are.

                  H Offline
                  H Offline
                  hskoglund
                  wrote on 3 May 2022, 00:41 last edited by
                  #11

                  @Chris-Kawa Yes, nice catch!
                  (I happened to have that #include from the sample above, in mainwindow.h, that's why it compiled ok for me.)

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    alatnet
                    wrote on 3 May 2022, 01:03 last edited by alatnet 5 Mar 2022, 01:17
                    #12

                    yep, that got me compiling with no issues!
                    Added "#include <winrt/Windows.Foundation.Collections.h>".

                    Now, i have a controller connected, via bluetooth (ps4 controller), and it's outputting some strange stuff when i use:

                    for (RawGameController c : myRawGameControllers){
                    	qDebug() << "- " << c.DisplayName();
                    }
                    

                    which is:

                    onecoreuap\xbox\devices\api\winrt\pnpapiwrapper.cpp(385)\Windows.Gaming.Input.dll!00007FFC5E04974A: (caller: 00007FFC5E04D528) ReturnHr(1) tid(1784) 8685C003
                    onecoreuap\xbox\devices\api\winrt\pnpapiwrapper.cpp(385)\Windows.Gaming.Input.dll!00007FFC5E04974A: (caller: 00007FFC5E04D528) ReturnHr(2) tid(1784) 8685C003
                    onecoreuap\xbox\devices\api\winrt\pnpapiwrapper.cpp(385)\Windows.Gaming.Input.dll!00007FFC5E04974A: (caller: 00007FFC5E04D528) ReturnHr(3) tid(1784) 8685C003
                    onecoreuap\xbox\devices\api\winrt\pnpapiwrapper.cpp(385)\Windows.Gaming.Input.dll!00007FFC5E04974A: (caller: 00007FFC5E04D528) ReturnHr(4) tid(1784) 8685C003
                    onecoreuap\xbox\devices\api\winrt\pnpapiwrapper.cpp(385)\Windows.Gaming.Input.dll!00007FFC5E04974A: (caller: 00007FFC5E04D528) ReturnHr(5) tid(1784) 8685C003
                    ...
                    mincore\com\oleaut32\dispatch\ups.cpp(2122)\OLEAUT32.dll!00007FFC6A509DD6: (caller: 00007FFC6A5091E9) ReturnHr(1) tid(5f44) 8002801D Library not registered.
                    

                    Note: i am doing test code with it being in the main function and after the QApplication a(argc, argv);.
                    Edit: did test it in my direct input code where i stuck it in a section of code that queried a list of devices, same thing.

                    1 Reply Last reply
                    0
                    • H Offline
                      H Offline
                      hskoglund
                      wrote on 3 May 2022, 06:49 last edited by hskoglund 5 Mar 2022, 07:00
                      #13

                      Hi, haven't got any game controllers so I cannot test, but it looks like you're getting exceptions thrown. Just guessing but maybe it's a permissions thing, perhaps you need to run as an Administrator and make sure you've enabled developer mode.

                      Edit: update: also see this StackOverflow post

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        alatnet
                        wrote on 3 May 2022, 13:42 last edited by alatnet 5 Mar 2022, 17:01
                        #14

                        ok, got it working!
                        Added "-lOLEAUT32" to win32:LIBS and added the following to the separate QThreads run function (whenever i used them) and the main function:

                        winrt::uninit_apartment();
                        winrt::init_apartment();
                        

                        So to condense all of this into one post (for those who are also trying to do what im doing):
                        .pro:

                        CONFIG += c++20
                        QMAKE_CXXFLAGS += /await:strict
                        win32:LIBS += -lwindowsapp -lOLEAUT32
                        

                        main.cpp:

                        #include <winrt/base.h>
                        int main(int argc, char *argv[])
                        {
                        	QApplication a(argc, argv);
                        
                        	winrt::uninit_apartment();
                        	winrt::init_apartment();
                        
                        	return a.exec();
                        }
                        

                        QThread derived classes:

                        #include <winrt/base.h>
                        class DerivedThread : public QThread {
                        public:
                        	DerivedThread (QThread* parent = nullptr) : QThread(parent) {}
                        
                        public:
                        	void run(){
                        		winrt::uninit_apartment();
                        		winrt::init_apartment();
                        		exec();
                        	}
                        };
                        

                        Those alone should get everything up and running to be able to use functions (aside from specific things like things requiring other things [looking at you collections...])

                        Now to create some qobject classes and get test out actual inputs!
                        Thank you all for your help!

                        Oh! Almost forgot this tidbit, make sure your build tools/sdk's are up to date!

                        EDIT: Looks like derived threads dont need to have the unint/init_appartment functions.

                        1 Reply Last reply
                        0

                        13/14

                        3 May 2022, 06:49

                        • Login

                        • Login or register to search.
                        13 out of 14
                        • First post
                          13/14
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved