Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. SIGNAL/SLOT() macros in Qt's source code
QtWS25 Last Chance

SIGNAL/SLOT() macros in Qt's source code

Scheduled Pinned Locked Moved Solved C++ Gurus
19 Posts 8 Posters 1.5k 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.
  • J Online
    J Online
    JonB
    wrote on 31 Oct 2024, 12:43 last edited by
    #1

    While browsing Qt6 source code at e.g. https://codebrowser.dev/qt6/qtbase/src/widgets/itemviews/qtableview.cpp.html#1367 I notice that internal signal/slot connections are still done with old-style SIGNAL/SLOT() string-based lookups (and I think this is used in all/many other classes). As a fan of PMF from the start of my Qt usage, why are they still done old way instead of new way? Is there some deep advantage or generic ability this offers from the lowest-level Qt code interface which would be missing with PMF?

    1 Reply Last reply
    0
    • A Offline
      A Offline
      Axel Spoerl
      Moderators
      wrote on 31 Oct 2024, 13:02 last edited by Axel Spoerl
      #2

      While it looks like something easy to change, disconnection during destruction is where it becomes tricky.
      SIGNAL/SLOT based connections get disconnected, when either of the owning classes gets destroyed.
      PMF connections stay alive, until the QObject is eventually destroyed.
      That can lead to crashes, if e.g. a signal is connected to &QLineEdit::setText and the line edit has become a plain QObject in the course of its destruction. When the signal is fired at this very moment, a dangling PMF would be called in a PMF based connection.
      A macro-based connection would have been gone already, so the signal would be dancing on its own.

      That said, I have learned my lesson fixing old style connections as a drive-by. You need to wrap your head around it and make sure they either don't cause any grief - or get disconnected at the right time.

      Software Engineer
      The Qt Company, Oslo

      J J S 3 Replies Last reply 31 Oct 2024, 13:10
      1
      • A Axel Spoerl
        31 Oct 2024, 13:02

        While it looks like something easy to change, disconnection during destruction is where it becomes tricky.
        SIGNAL/SLOT based connections get disconnected, when either of the owning classes gets destroyed.
        PMF connections stay alive, until the QObject is eventually destroyed.
        That can lead to crashes, if e.g. a signal is connected to &QLineEdit::setText and the line edit has become a plain QObject in the course of its destruction. When the signal is fired at this very moment, a dangling PMF would be called in a PMF based connection.
        A macro-based connection would have been gone already, so the signal would be dancing on its own.

        That said, I have learned my lesson fixing old style connections as a drive-by. You need to wrap your head around it and make sure they either don't cause any grief - or get disconnected at the right time.

        J Offline
        J Offline
        J.Hilk
        Moderators
        wrote on 31 Oct 2024, 13:10 last edited by
        #3

        @Axel-Spoerl and here I thought it was because no-one touched that class since 2016... 🙈


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        1 Reply Last reply
        0
        • A Axel Spoerl
          31 Oct 2024, 13:02

          While it looks like something easy to change, disconnection during destruction is where it becomes tricky.
          SIGNAL/SLOT based connections get disconnected, when either of the owning classes gets destroyed.
          PMF connections stay alive, until the QObject is eventually destroyed.
          That can lead to crashes, if e.g. a signal is connected to &QLineEdit::setText and the line edit has become a plain QObject in the course of its destruction. When the signal is fired at this very moment, a dangling PMF would be called in a PMF based connection.
          A macro-based connection would have been gone already, so the signal would be dancing on its own.

          That said, I have learned my lesson fixing old style connections as a drive-by. You need to wrap your head around it and make sure they either don't cause any grief - or get disconnected at the right time.

          J Online
          J Online
          JonB
          wrote on 31 Oct 2024, 13:40 last edited by
          #4

          @Axel-Spoerl said in SIGNAL/SLOT() macros in Qt's source code:

          disconnection during destruction is where it becomes tricky

          Fair enough. But if Qt cannot get this correct, whatever it takes, in their own supplied code and so stick with old-style, what hope for us amateurs when we do use PMF in our own stuff?!

          1 Reply Last reply
          0
          • C Online
            C Online
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on 31 Oct 2024, 13:48 last edited by
            #5

            Qt can do it correct but there are a lot of corner cases inside Qt which are hard to find out and there is a lack of manpower to change it. Also there is no reason to change it as it works.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            1
            • J Online
              J Online
              JonB
              wrote on 31 Oct 2024, 13:58 last edited by JonB
              #6

              Fair enough to @Axel-Spoerl & @Christian-Ehrlicher's answers.

              One minor irritation for me, as an online code browser (don't know if this also arises if you have source inside your IDE code model, but I suspect it does). I was trying to find where all the calls are in Qt source to QTableView::columnCountChanged(). Since it's a protected slot I know Qt source must call it. But the "helper" in code browser which allows you to see/go to all calls to a function, which I use a lot, was showing it only had 1 definition in .cpp and 1 declaration in .h, i.e. not used anywhere. I had to do a bit of searching to discover https://codebrowser.dev/qt6/qtbase/src/widgets/itemviews/qtableview.cpp.html#1371

              connect(d->horizontalHeader, SIGNAL(sectionCountChanged(int,int)),
                      this, SLOT(columnCountChanged(int,int)));
              

              since that does not show up as a call to sectionCountChanged() because of the macro-to-string, where a PMF connection would have allowed the code browser to spot it.

              1 Reply Last reply
              0
              • A Offline
                A Offline
                Axel Spoerl
                Moderators
                wrote on 31 Oct 2024, 14:03 last edited by
                #7

                I fully agree with you, that macro based connections should all be removed.
                @Christian-Ehrlicher has submitted cleanups, and should you find it tempting to submit patches - we'd be grateful.
                I also clean them up whenever I find the time for it. Unfortunately there are other priorities, too. For all of us.

                Software Engineer
                The Qt Company, Oslo

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  GrecKo
                  Qt Champions 2018
                  wrote on 31 Oct 2024, 14:05 last edited by
                  #8

                  Note that SIGNAL/SLOT syntax can also be used to add virtual dispatch to a function while not changing the binary compatibility of a class.
                  Like https://doc.qt.io/qt-5/qnetworkaccessmanager.html#supportedSchemesImplementation that was added as a protected slot in Qt 5.2 because adding a virtual method was not possible until Qt 6.

                  J 1 Reply Last reply 31 Oct 2024, 14:11
                  4
                  • G GrecKo
                    31 Oct 2024, 14:05

                    Note that SIGNAL/SLOT syntax can also be used to add virtual dispatch to a function while not changing the binary compatibility of a class.
                    Like https://doc.qt.io/qt-5/qnetworkaccessmanager.html#supportedSchemesImplementation that was added as a protected slot in Qt 5.2 because adding a virtual method was not possible until Qt 6.

                    J Online
                    J Online
                    JonB
                    wrote on 31 Oct 2024, 14:11 last edited by
                    #9

                    @GrecKo
                    Yes, I knew there were some "advanced" reasons/cases where (apparently) one has to use old-style. I just wondered whether there was any good reason why, say, the example I came across needed to use it. It seems not.

                    P 1 Reply Last reply 1 Nov 2024, 02:10
                    0
                    • C Online
                      C Online
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on 31 Oct 2024, 14:13 last edited by
                      #10

                      If you see the old signal/slot syntax in official Qt examples let us know so we can remove them - they should no longer be advertised.

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      S 1 Reply Last reply 31 Oct 2024, 16:45
                      0
                      • J JonB has marked this topic as solved on 31 Oct 2024, 14:13
                      • C Christian Ehrlicher
                        31 Oct 2024, 14:13

                        If you see the old signal/slot syntax in official Qt examples let us know so we can remove them - they should no longer be advertised.

                        S Offline
                        S Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on 31 Oct 2024, 16:45 last edited by
                        #11

                        @Christian-Ehrlicher AFAIK, I took care of that except in some places where it was really not possible.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        1
                        • J JonB
                          31 Oct 2024, 14:11

                          @GrecKo
                          Yes, I knew there were some "advanced" reasons/cases where (apparently) one has to use old-style. I just wondered whether there was any good reason why, say, the example I came across needed to use it. It seems not.

                          P Offline
                          P Offline
                          Pl45m4
                          wrote on 1 Nov 2024, 02:10 last edited by
                          #12

                          Hi @JonB ,

                          I was also asking this myself when I was browsing the Qt source for my topic here.
                          There you can also find interesting mentions made by @Christian-Ehrlicher and @SGaist .

                          For example, I learned that the string-based and the PMF/Functor-based syntax are interchangeable in most cases, but not everywhere, as it is a widely spread myth :)
                          With both ways to connect you can do things the other way does not support.


                          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                          ~E. W. Dijkstra

                          1 Reply Last reply
                          0
                          • A Axel Spoerl
                            31 Oct 2024, 13:02

                            While it looks like something easy to change, disconnection during destruction is where it becomes tricky.
                            SIGNAL/SLOT based connections get disconnected, when either of the owning classes gets destroyed.
                            PMF connections stay alive, until the QObject is eventually destroyed.
                            That can lead to crashes, if e.g. a signal is connected to &QLineEdit::setText and the line edit has become a plain QObject in the course of its destruction. When the signal is fired at this very moment, a dangling PMF would be called in a PMF based connection.
                            A macro-based connection would have been gone already, so the signal would be dancing on its own.

                            That said, I have learned my lesson fixing old style connections as a drive-by. You need to wrap your head around it and make sure they either don't cause any grief - or get disconnected at the right time.

                            S Offline
                            S Offline
                            SimonSchroeder
                            wrote on 4 Nov 2024, 10:26 last edited by
                            #13

                            @Axel-Spoerl said in SIGNAL/SLOT() macros in Qt's source code:

                            While it looks like something easy to change, disconnection during destruction is where it becomes tricky.
                            SIGNAL/SLOT based connections get disconnected, when either of the owning classes gets destroyed.
                            PMF connections stay alive, until the QObject is eventually destroyed.
                            That can lead to crashes, if e.g. a signal is connected to &QLineEdit::setText and the line edit has become a plain QObject in the course of its destruction. When the signal is fired at this very moment, a dangling PMF would be called in a PMF based connection.
                            A macro-based connection would have been gone already, so the signal would be dancing on its own.

                            I don't fully understand what you are saying here. I always thought that as long as you have a context object PMF and SIGNAL/SLOT would behave the same. Sure, lambdas cannot be disconnected automatically without a context object.

                            Where exactly is the problem? Does only SLOT enter the connection into a list of connected slots for the receiver and the PMF syntax does not do this? Is there a reason for this decision? Still, there must be some information saved to inform all potential senders at the point when the QObject base type is destructed.

                            @Pl45m4 said in SIGNAL/SLOT() macros in Qt's source code:

                            With both ways to connect you can do things the other way does not support.

                            Can you point to some differences? I only can think about new things the PMF syntax supports, like connecting to functions not declared as slots (i.e. even member functions of class not derived from QObject) and connecting to lambdas. What are things you can to with the string-based syntax that is impossible with PMF?

                            P 1 Reply Last reply 4 Nov 2024, 12:26
                            1
                            • A Offline
                              A Offline
                              Axel Spoerl
                              Moderators
                              wrote on 4 Nov 2024, 11:30 last edited by
                              #14

                              IMHO, as a general rule, it's safe to use PMF syntax in applications.
                              The difference between "old" and "new" style kicks in when cascaded destruction takes place, and a signal is delivered to a stale object. In the Qt library, this happens (amongst others) to slots in private headers.

                              You can have a look at https://codereview.qt-project.org/c/qt/qtbase/+/507788 for instance.
                              Just replacing string based connections with PMF syntax lead to crashes, when the model of a combo box would still emit signals to the box's private header when it was already destroyed. QMetaObject deals with this automatically, because it knows to which class the connection belongs. A PMF connection doesn't know when the slot object's d'tor is reached, so it needs to be explicitly disconnected. Otherwise a signal could be delivered to QComboBoxPrivate when it has already degraded to a plain QObjectPrivate.

                              Software Engineer
                              The Qt Company, Oslo

                              J 1 Reply Last reply 4 Nov 2024, 11:36
                              1
                              • A Axel Spoerl
                                4 Nov 2024, 11:30

                                IMHO, as a general rule, it's safe to use PMF syntax in applications.
                                The difference between "old" and "new" style kicks in when cascaded destruction takes place, and a signal is delivered to a stale object. In the Qt library, this happens (amongst others) to slots in private headers.

                                You can have a look at https://codereview.qt-project.org/c/qt/qtbase/+/507788 for instance.
                                Just replacing string based connections with PMF syntax lead to crashes, when the model of a combo box would still emit signals to the box's private header when it was already destroyed. QMetaObject deals with this automatically, because it knows to which class the connection belongs. A PMF connection doesn't know when the slot object's d'tor is reached, so it needs to be explicitly disconnected. Otherwise a signal could be delivered to QComboBoxPrivate when it has already degraded to a plain QObjectPrivate.

                                J Online
                                J Online
                                JonB
                                wrote on 4 Nov 2024, 11:36 last edited by
                                #15

                                @Axel-Spoerl said in SIGNAL/SLOT() macros in Qt's source code:

                                A PMF connection doesn't know when the slot object's d'tor is reached, so it needs to be explicitly disconnected.

                                Whaatt?! In user code (as opposed to whatever private inside Qt for its own purposes)?? I only use PMF, I have never had a problem, I am expecting it to deal with either signal or slot object being destroyed without my having to do anything. I suppose I may never have tested a slot object deletion, not sure...

                                1 Reply Last reply
                                0
                                • A Offline
                                  A Offline
                                  Axel Spoerl
                                  Moderators
                                  wrote on 4 Nov 2024, 12:03 last edited by
                                  #16

                                  Whaatt?!

                                  I guess you will never experience any issue with PMF based connections, unless you start plumbing with private classes created next to your public ones, go for multiple inheritance cascades and complex destruction with signals emitted to private headers.
                                  I don't want to create any panic, I am just answering the question why we don't simply remove all string based connections in our code.

                                  Software Engineer
                                  The Qt Company, Oslo

                                  1 Reply Last reply
                                  2
                                  • S SimonSchroeder
                                    4 Nov 2024, 10:26

                                    @Axel-Spoerl said in SIGNAL/SLOT() macros in Qt's source code:

                                    While it looks like something easy to change, disconnection during destruction is where it becomes tricky.
                                    SIGNAL/SLOT based connections get disconnected, when either of the owning classes gets destroyed.
                                    PMF connections stay alive, until the QObject is eventually destroyed.
                                    That can lead to crashes, if e.g. a signal is connected to &QLineEdit::setText and the line edit has become a plain QObject in the course of its destruction. When the signal is fired at this very moment, a dangling PMF would be called in a PMF based connection.
                                    A macro-based connection would have been gone already, so the signal would be dancing on its own.

                                    I don't fully understand what you are saying here. I always thought that as long as you have a context object PMF and SIGNAL/SLOT would behave the same. Sure, lambdas cannot be disconnected automatically without a context object.

                                    Where exactly is the problem? Does only SLOT enter the connection into a list of connected slots for the receiver and the PMF syntax does not do this? Is there a reason for this decision? Still, there must be some information saved to inform all potential senders at the point when the QObject base type is destructed.

                                    @Pl45m4 said in SIGNAL/SLOT() macros in Qt's source code:

                                    With both ways to connect you can do things the other way does not support.

                                    Can you point to some differences? I only can think about new things the PMF syntax supports, like connecting to functions not declared as slots (i.e. even member functions of class not derived from QObject) and connecting to lambdas. What are things you can to with the string-based syntax that is impossible with PMF?

                                    P Offline
                                    P Offline
                                    Pl45m4
                                    wrote on 4 Nov 2024, 12:26 last edited by Pl45m4 11 Apr 2024, 12:27
                                    #17

                                    @SimonSchroeder said in SIGNAL/SLOT() macros in Qt's source code:

                                    What are things you can to with the string-based syntax that is impossible with PMF?

                                    What @Christian-Ehrlicher said here

                                    • https://forum.qt.io/post/804827

                                    and here

                                    • https://forum.qt.io/post/804829

                                    That's (one of ) the reason(s) why the String-based syntax is still used with Qt's pImpl implementation and for "private slots".

                                    AFAIK the PMF can connect to non slot-declared functions, but only within QObject-derived classes.
                                    The string-based connection does not need QObject receiver.


                                    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                                    ~E. W. Dijkstra

                                    G 1 Reply Last reply 4 Nov 2024, 16:44
                                    1
                                    • P Pl45m4
                                      4 Nov 2024, 12:26

                                      @SimonSchroeder said in SIGNAL/SLOT() macros in Qt's source code:

                                      What are things you can to with the string-based syntax that is impossible with PMF?

                                      What @Christian-Ehrlicher said here

                                      • https://forum.qt.io/post/804827

                                      and here

                                      • https://forum.qt.io/post/804829

                                      That's (one of ) the reason(s) why the String-based syntax is still used with Qt's pImpl implementation and for "private slots".

                                      AFAIK the PMF can connect to non slot-declared functions, but only within QObject-derived classes.
                                      The string-based connection does not need QObject receiver.

                                      G Offline
                                      G Offline
                                      GrecKo
                                      Qt Champions 2018
                                      wrote on 4 Nov 2024, 16:44 last edited by
                                      #18

                                      @Pl45m4 said in SIGNAL/SLOT() macros in Qt's source code:

                                      The string-based connection does not need QObject receiver.

                                      The signature is QObject::connect(const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType ) though

                                      S 1 Reply Last reply 4 Nov 2024, 16:56
                                      0
                                      • G GrecKo
                                        4 Nov 2024, 16:44

                                        @Pl45m4 said in SIGNAL/SLOT() macros in Qt's source code:

                                        The string-based connection does not need QObject receiver.

                                        The signature is QObject::connect(const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType ) though

                                        S Offline
                                        S Offline
                                        SGaist
                                        Lifetime Qt Champion
                                        wrote on 4 Nov 2024, 16:56 last edited by
                                        #19

                                        @GrecKo said in SIGNAL/SLOT() macros in Qt's source code:

                                        @Pl45m4 said in SIGNAL/SLOT() macros in Qt's source code:

                                        The string-based connection does not need QObject receiver.

                                        The signature is QObject::connect(const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType ) though

                                        This was referring to this overload:

                                        QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) const
                                        

                                        Which implies that the target is the current object.

                                        This is different from the similar (yet different) PMF variant as there's no implicit target in that case. Hence the recommendation to use the variant which has a context object.

                                        Interested in AI ? www.idiap.ch
                                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                        1 Reply Last reply
                                        0

                                        4/19

                                        31 Oct 2024, 13:40

                                        topic:navigator.unread, 15
                                        • Login

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