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. Standard C++ callbacks handling inside Qt application

Standard C++ callbacks handling inside Qt application

Scheduled Pinned Locked Moved Solved General and Desktop
17 Posts 6 Posters 3.8k Views 3 Watching
  • 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.
  • mranger90M Offline
    mranger90M Offline
    mranger90
    wrote on last edited by
    #5

    I'm not sure how this would work with a lambda. You might try to create a static member function and pass a pointer to that function. With a static function, you are going to need a pointer to mainWindow, since you wont get "this". A lot of libraries that use callbacks allow you to pass a pointer to "this" as a void * argument for just this purpose.
    i.e.
    MainWindow.h

    static void onNewSystem();
    

    MainWindow.cpp

    mavsdk.subscribe_on_new_system(&MainWindow::onNewSystem);
    
    MainWindow::onNewSystem()
    {
       // assume that a pointer to MainWindow is set somewhere
       mainWindow->setWindowTitle("Connected.");
    
    DragoonD 1 Reply Last reply
    0
    • DragoonD Dragoon

      Hi I'm a newbie in Qt and I got stuck into a problem I'm not able to handle, I'm using an external library that implements some feature trough callbacks.
      AFAIK this llibrary uses different threads to manage such callback. As a result I'm not able to manage such calls:

      void MainWindow::connectMAV()
      {
          mavsdk::ConnectionResult conn_result = mavsdk.add_any_connection("localhost:5000");
      
          setWindowTitle("Listening");
      
          mavsdk.subscribe_on_new_system
          (
              [&]()
              {
                  setWindowTitle("Connected");
                  system = mavsdk.systems()[0];
              }
          );
      }
      

      In the above code the internal lambda function is never called.
      On identical non Qt C++ application the callback is triggered correctly.
      I think the problem is the interaction with the event loop management of Qt.
      There's a workaround?

      Best regards,
      Mike

      S Offline
      S Offline
      SimonSchroeder
      wrote on last edited by
      #6

      @Dragoon said in Standard C++ callbacks handling inside Qt application:

      AFAIK this llibrary uses different threads to manage such callback.

      This might be one more problem. You need to call setWindowTitle() within the main GUI thread. In addition to previous fixes suggested, why don't you just write to the console if your lambda function gets called? Because it might actually be called but not do what you expect.

      The easiest way to have something done in the GUI thread is for your callback to just trigger a signal which is connected to a slot that does the actual work (i.e. call setWindowTitle()).

      DragoonD 1 Reply Last reply
      1
      • S SimonSchroeder

        @Dragoon said in Standard C++ callbacks handling inside Qt application:

        AFAIK this llibrary uses different threads to manage such callback.

        This might be one more problem. You need to call setWindowTitle() within the main GUI thread. In addition to previous fixes suggested, why don't you just write to the console if your lambda function gets called? Because it might actually be called but not do what you expect.

        The easiest way to have something done in the GUI thread is for your callback to just trigger a signal which is connected to a slot that does the actual work (i.e. call setWindowTitle()).

        DragoonD Offline
        DragoonD Offline
        Dragoon
        wrote on last edited by
        #7

        @SimonSchroeder I'll try this approach...

        bye by[t]e{s}... Mike

        DragoonD 1 Reply Last reply
        0
        • DragoonD Dragoon

          @SimonSchroeder I'll try this approach...

          DragoonD Offline
          DragoonD Offline
          Dragoon
          wrote on last edited by Dragoon
          #8

          @SimonSchroeder tried and failed.

           missionServer->subscribe_incoming_mission(
             [&](mavsdk::MissionRawServer::Result result, mavsdk::MissionRawServer::MissionPlan plan)
             {
                emit incomingMission(result, plan);
             }
          );
          
          void MainWindow::onIncomingMission(MissionRawServer::Result result, MissionRawServer::MissionPlan plan)
          {   
                 Q_UNUSED(result);
                 Q_UNUSED(plan);
                  missions++;
          }
          

          Debugging it I can see callback being triggered but incominMission() never being fired.

          bye by[t]e{s}... Mike

          1 Reply Last reply
          0
          • JonBJ JonB

            @Dragoon
            I don't see how anyone will know what issue there might be in your code or Qt's with some third-party library.

            Although you say the lambda is never called, if it were and you say it comes from another thread in Qt you would not be allowed to perform setWindowTitle("Connected") from a non-UI thread.

            DragoonD Offline
            DragoonD Offline
            Dragoon
            wrote on last edited by Dragoon
            #9

            @JonB the third party library could not be the main issue in this. The problem is the management of C++ 17 standard callbacks.
            And, BTW, even:

            missions++;
            

            (being mission an int variable) is never executed.

            bye by[t]e{s}... Mike

            jsulmJ 1 Reply Last reply
            0
            • DragoonD Dragoon

              @JonB the third party library could not be the main issue in this. The problem is the management of C++ 17 standard callbacks.
              And, BTW, even:

              missions++;
              

              (being mission an int variable) is never executed.

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #10

              @Dragoon Did you make sure you connected incomingMission successfully to onIncomingMission? Did you check the lifetime of the involved objects? If the lambda is called then the signal is for sure emitted. Most probably you did not connect signal/slot.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              DragoonD 1 Reply Last reply
              0
              • mranger90M mranger90

                I'm not sure how this would work with a lambda. You might try to create a static member function and pass a pointer to that function. With a static function, you are going to need a pointer to mainWindow, since you wont get "this". A lot of libraries that use callbacks allow you to pass a pointer to "this" as a void * argument for just this purpose.
                i.e.
                MainWindow.h

                static void onNewSystem();
                

                MainWindow.cpp

                mavsdk.subscribe_on_new_system(&MainWindow::onNewSystem);
                
                MainWindow::onNewSystem()
                {
                   // assume that a pointer to MainWindow is set somewhere
                   mainWindow->setWindowTitle("Connected.");
                
                DragoonD Offline
                DragoonD Offline
                Dragoon
                wrote on last edited by
                #11

                @mranger90
                defining 'slots' as static member seem to work.
                The problem now is to access MainWindow instance...

                bye by[t]e{s}... Mike

                jsulmJ 1 Reply Last reply
                0
                • DragoonD Dragoon

                  @mranger90
                  defining 'slots' as static member seem to work.
                  The problem now is to access MainWindow instance...

                  jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on last edited by
                  #12

                  @Dragoon said in Standard C++ callbacks handling inside Qt application:

                  defining 'slots' as static member seem to work

                  Why static?!
                  Can you show how and what you're actually connecting?

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • jsulmJ jsulm

                    @Dragoon Did you make sure you connected incomingMission successfully to onIncomingMission? Did you check the lifetime of the involved objects? If the lambda is called then the signal is for sure emitted. Most probably you did not connect signal/slot.

                    DragoonD Offline
                    DragoonD Offline
                    Dragoon
                    wrote on last edited by Dragoon
                    #13

                    @jsulm said in Standard C++ callbacks handling inside Qt application:

                    Most probably you did not connect signal/slot.

                    I'm not SO newbie... ;-)

                    MainWindow::MainWindow(QWidget *parent)
                        : QMainWindow(parent)
                        , ui(new Ui::MainWindow)
                        , configuration(Mavsdk::Configuration::UsageType::Autopilot)
                        , eventTimer(new QTimer(this))
                    
                    {
                        ui->setupUi(this);
                    
                        connect(this, &MainWindow::newSystem, this, &MainWindow::onNewSystem);
                        connect(this, &MainWindow::incomingMission, this, &MainWindow::onIncomingMission);
                        connect(eventTimer, &QTimer::timeout, this, &MainWindow::onUpdateEvent);
                    
                        initMAVSDK();
                        initMAVConnection();
                    }
                    
                    void MainWindow::initMAVSDK()
                    {
                        configuration.set_system_id(DEF_ID);
                    
                        mavsdk.set_configuration(configuration);
                    }
                    
                    void MainWindow::initMAVConnection()
                    {
                        ConnectionResult conn_result = mavsdk.add_any_connection(DEF_URL.toStdString());  
                    
                        if(conn_result == mavsdk::ConnectionResult::Success)
                        {
                            mavsdk.subscribe_on_new_system(
                                [&](){
                                    emit newSystem();
                                }
                            );
                    
                            eventTimer->start(DEF_UPDATE_TIMEOUT);
                        }
                    }
                    

                    bye by[t]e{s}... Mike

                    1 Reply Last reply
                    0
                    • DragoonD Offline
                      DragoonD Offline
                      Dragoon
                      wrote on last edited by Dragoon
                      #14

                      it seems that I found the real issue...
                      I need to put these lines:

                      Q_DECLARE_METATYPE(MissionRawServer::Result)
                      Q_DECLARE_METATYPE(MissionRawServer::MissionPlan)
                      

                      in my class header

                      and these:

                      qRegisterMetaType<MissionRawServer::Result>();
                      qRegisterMetaType<MissionRawServer::MissionPlan>();
                      

                      prior connect calls.

                      Probably since parameters on callback where not QObject derivative they needed to be registered to be connect proof.

                      I don't know it this's the correct register procedure and explanation of this issue but now ti seem to be fixed.
                      Could someone confirm?

                      bye by[t]e{s}... Mike

                      jsulmJ 1 Reply Last reply
                      2
                      • DragoonD Dragoon

                        it seems that I found the real issue...
                        I need to put these lines:

                        Q_DECLARE_METATYPE(MissionRawServer::Result)
                        Q_DECLARE_METATYPE(MissionRawServer::MissionPlan)
                        

                        in my class header

                        and these:

                        qRegisterMetaType<MissionRawServer::Result>();
                        qRegisterMetaType<MissionRawServer::MissionPlan>();
                        

                        prior connect calls.

                        Probably since parameters on callback where not QObject derivative they needed to be registered to be connect proof.

                        I don't know it this's the correct register procedure and explanation of this issue but now ti seem to be fixed.
                        Could someone confirm?

                        jsulmJ Offline
                        jsulmJ Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on last edited by
                        #15

                        @Dragoon said in Standard C++ callbacks handling inside Qt application:

                        I need to put these lines

                        Ah, yes you're right. If you use your own custom data types as parameters for signals/slots you have to register them.

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        1
                        • Kent-DorfmanK Offline
                          Kent-DorfmanK Offline
                          Kent-Dorfman
                          wrote on last edited by
                          #16

                          @Dragoon so should this be marked as solved?

                          The dystopian literature that served as a warning in my youth has become an instruction manual in my elder years.

                          DragoonD 1 Reply Last reply
                          0
                          • Kent-DorfmanK Kent-Dorfman

                            @Dragoon so should this be marked as solved?

                            DragoonD Offline
                            DragoonD Offline
                            Dragoon
                            wrote on last edited by
                            #17

                            @Kent-Dorfman I do.

                            bye by[t]e{s}... Mike

                            1 Reply Last reply
                            0

                            • Login

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