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. Connect an external library call by signals and slots
Qt 6.11 is out! See what's new in the release blog

Connect an external library call by signals and slots

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 5 Posters 2.4k Views 1 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.
  • S Offline
    S Offline
    szumial
    wrote on last edited by
    #1

    Hi! I'd like to ask if using the signals and slots mechanism is possible when using a static library which is not written with Qt? Let's say the setup is like this:

    • Qt project with GUI, static library linked
    • A class in this Qt project utilizes some of the library methods
    • Each time an action is performed in this library, it sets a message string
    • It does provide a getMessage() kind of method to retrieve the current string

    Since the library cannot emit any signals, is it at all possible to get the changing messages in the GUI application? I thought of a solution with using a QTimer with a short timeout, which would run and probe the library by calling its getMessage function. This doesn't seem right though for several reasons: the timeout would have to be very short = resource hungry, plus I could still miss the messages by calling the getMessage() at a wrong time.

    Somewhere arount the Internet I found someone suggesting to wrap the library calls in some Qt class, but I don't have an idea on how I should start with something like this.

    Here's some pseudo-code to explain what I'd like to achieve.

    // External library
    
    bool ClassA::doSomething()
    {
        // Perform an action
        setMessage("Message1");
    
        // Perform another action
        setMessage("Message2");
    
        ...
    
        return true;
    }
    
    // Qt application
    
    LibraryA::ClassA *classA = new LibraryA::ClassA();
    
    connect(classA, &LibraryA::ClassA::setMessage, this, &MainWindow::receiveMessage);
    
    classA->doSomething();
    
    void MainWindow::receiveMessage()
    {
        QString messageReceived = QString::fromStdString(classA->getMessage());
        ui->textBrowser->append(messageReceived);       
    }
    
    ``
    JonBJ 1 Reply Last reply
    0
    • S szumial

      Hi! I'd like to ask if using the signals and slots mechanism is possible when using a static library which is not written with Qt? Let's say the setup is like this:

      • Qt project with GUI, static library linked
      • A class in this Qt project utilizes some of the library methods
      • Each time an action is performed in this library, it sets a message string
      • It does provide a getMessage() kind of method to retrieve the current string

      Since the library cannot emit any signals, is it at all possible to get the changing messages in the GUI application? I thought of a solution with using a QTimer with a short timeout, which would run and probe the library by calling its getMessage function. This doesn't seem right though for several reasons: the timeout would have to be very short = resource hungry, plus I could still miss the messages by calling the getMessage() at a wrong time.

      Somewhere arount the Internet I found someone suggesting to wrap the library calls in some Qt class, but I don't have an idea on how I should start with something like this.

      Here's some pseudo-code to explain what I'd like to achieve.

      // External library
      
      bool ClassA::doSomething()
      {
          // Perform an action
          setMessage("Message1");
      
          // Perform another action
          setMessage("Message2");
      
          ...
      
          return true;
      }
      
      // Qt application
      
      LibraryA::ClassA *classA = new LibraryA::ClassA();
      
      connect(classA, &LibraryA::ClassA::setMessage, this, &MainWindow::receiveMessage);
      
      classA->doSomething();
      
      void MainWindow::receiveMessage()
      {
          QString messageReceived = QString::fromStdString(classA->getMessage());
          ui->textBrowser->append(messageReceived);       
      }
      
      ``
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @szumial
      While you wait for somebody more knowledgeable than I to answer.

      You won't be able to do the connect(classA, &LibraryA::ClassA::setMessage, this, &MainWindow::receiveMessage); because, of course, the external library's LibraryA::ClassA::setMessage won't be a Qt signal.

      It seems to me there can only be two possibilities:

      • ClassA::doSomething(), or the setMessage()s it calls, must be changed to call something Qt to emit a signal. But if you can't change source, or cannot call/include anything Qt however indirectly, it can't. You cannot miraculously "know" that some value has changed or some function has been called in that separate library. If you can have, say, an external function pointer that it calls which you can set to invoke something in Qt that would be great, but otherwise it gets you nowhere.

      • Which leaves some kind of QTimer in the Qt side which will "poll" whatever to see if somethings has changed in the other library and then raise a Qt signal.

      the timeout would have to be very short = resource hungry, plus I could still miss the messages by calling the getMessage() at a wrong time.

      It would have to be as short as the minimum delay acceptable to you to notice whatever had changed. Not necessarily "resource hungry" per se, not ideal, but not that bad, if your frequency is not too short.

      You shouldn't be "missing messages by calling getMessage() at the wrong time". You would have to arrange that this getMessage() gets the last message, or messages, at the external side because that "buffered" or "saved" when whatever event occurred and returned it at the next getMessage() call.

      1 Reply Last reply
      2
      • gde23G Offline
        gde23G Offline
        gde23
        wrote on last edited by
        #3

        If its as simple as in your example then I would go totally without signals slots

        Just don't call doSomething() method of the class but make a wrapper class in mainwindow and let Class::doSomthing() return the string

        QString ClassA::doSomething()
        {
            // Perform an action
            return("Message1");
        }
        

        wrapper in mainwindow:

        void MainWindow::doSomething()
        {
            QString messageReceived = m_classA->doSomething() // do something now directly returns the 
            ui->textBrowser->append(messageReceived);       
        }
        

        and this is how you call it

        // class is a member variable of mainwindow
        LibraryA::ClassA *m_classA = new LibraryA::ClassA();
        this->doSomething();
        
        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          is ClassA::setMessage declared as virtual and public or protected?
          If so then it's trivial:

          // Qt application
          class ClassQA : public QObject, public LibraryA::ClassA{
          Q_OBJECT
          public:
          using ClassA::ClassA;
          signals:
          void messageChanged();
          protected: // here I assume it's protected
          void setMessage(const std::string& msg) override{
          LibraryA::ClassA::setMessage(msg);
          messageChanged();
          }
          };
          ClassQA *classA = new ClassQA();
          connect(classA, &ClassQA::messageChanged, this, &MainWindow::receiveMessage);
          

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          2
          • S Offline
            S Offline
            szumial
            wrote on last edited by
            #5

            Thanks for the helpful answers! I do have access to the lower layer library code and I can change it, however, I cannot add Qt proprietary code to it. The setMessage method could be made virtual and I will try with this solution and post the results as soon as I get it working.

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

              To interface with a third party library you need an interface layer. You need to decide under what circumstances you need to call those 3rd party routines, and then you have a choice to make:

              1. create a separate event loop thread that links Qt signals/slots to the callbacks,
              2. use a timer to poll the callbacks
              3. extend the Qt event loop to poll/handle the callbacks directly

              most of the time I'd choose option number 1.

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

              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