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. Multiple Inheritance of Interfaces with Slots
Forum Updated to NodeBB v4.3 + New Features

Multiple Inheritance of Interfaces with Slots

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 4 Posters 1.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.
  • K Offline
    K Offline
    kain
    wrote on 2 Jan 2019, 15:04 last edited by kain 1 Feb 2019, 15:05
    #1

    Hello,

    I need some advise on how I can achieve to implement multiple interfaces with Qt.
    I got a class which handles communication to different periphiere-cards on an RS485-bus 'PeripherieCommunicator'.
    This class includes several interfaces, each declaring the communication to one of these cards in the RS485-bus, for example:

    class IPR112Control
    {
    public:
        virtual ~IPR112Control() {}
    public slots:
        virtual signed short ssPR112ReadShortState( STATE * pstrShortState, int addr) = 0;
    };
    Q_DECLARE_INTERFACE(IPR112Control, "IPR112Control/1.0")
    

    and

    class IPR144Control
    {
    public:
        virtual ~IPR144Control() {}
    public slots:
        virtual signed short ssPR144GetFullDeviceInfo( INFO * pstrFullDeviceInfo, int addr ) = 0;
    };
    Q_DECLARE_INTERFACE(IPR144Control, "IPR144Control/1.0")
    

    My class PeripherieCommunicator implements those 2 interfaces:

    class PeripherieCommunicator : public QObject, IPR112Control,  public IPR144Control
    {
        Q_OBJECT
        Q_INTERFACES(IPR112Control)
        Q_INTERFACES(IPR144Control)
    ...
    // IPR112Control interface
    public slots:
        signed short ssPR112ReadShortState( STATE * pstrShortState, int addr);
    // IPR144Control interface
    public slots:
        signed short ssPR144GetFullDeviceInfo( INFO * pstrFullDeviceInfo, int addr ) = 0;
    }
    

    The Problem occurs when I try to connect to those slots using the Interface, i.e.:

    MotorControl::MotorControl(IPR112Control *pcom, QObject *parent) : QObject(parent)
    {
        this->pcom = pcom;
        connect(this, &MotorControl::readShortState, this->pcom, &IPR112Control::ssPR112ReadShortState, Qt::ConnectionType::BlockingQueuedConnection);
    

    The problem seems to be that my Interface IPR112Control (and other interfaces) does not inherit from QObject but when I change them to inherit QObject I get errors in my PeripherieCommunicator class since the reference to QObject is ambigous then.
    Is there any advice on how to fix this problem in a proper way? Of course I could just inject the pointer to 'PeripherieCommunicator' in the constructor of 'MotorControl' but this would make the class less testable. The other way I see is to merge all Interfaces into one single interface but this does not seem the right way either...

    1 Reply Last reply
    0
    • V Offline
      V Offline
      VRonin
      wrote on 2 Jan 2019, 15:15 last edited by VRonin 1 Feb 2019, 15:34
      #2

      Try changing it to connect(this, &MotorControl::readShortState, this, std::bind(&IPR112Control::ssPR112ReadShortState, this->pcom, std::placeholders::_1, std::placeholders::_2), Qt::ConnectionType::BlockingQueuedConnection);

      The only problem now is that you need to make sure this->pcom does not get destroyed while there's still a pending slot to be executed and this was destroyed.

      If that's a problem then save the return of the connect: pcomConnection = QObject::connect(this, &MotorControl::readShortState, this->pcom, std::bind(&IPR112Control::ssPR112ReadShortState,std::placeholders::_1,std::placeholders::_2), Qt::ConnectionType::BlockingQueuedConnection); and then call QObject::disconnect(pcomConnection); before the deletion of this->pcom and replace the deletion with a delayed one:

      auto pcomToDelete = this->pcom;
      QTimer::singleShot(0,[pcomToDelete]()->void{delete pcomToDelete;});
      

      "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

      K 1 Reply Last reply 2 Jan 2019, 18:31
      0
      • C Offline
        C Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on 2 Jan 2019, 15:59 last edited by
        #3

        Wouldn't a simple cast to IPR112Control help here?

        IPR112Control *ifc = pcom;
        connect(this, &MotorControl::readShortState, ifc, &IPR112Control::ssPR112ReadShortState, Qt::ConnectionType::BlockingQueuedConnection);
        

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

        K V 2 Replies Last reply 2 Jan 2019, 16:34
        0
        • C Christian Ehrlicher
          2 Jan 2019, 15:59

          Wouldn't a simple cast to IPR112Control help here?

          IPR112Control *ifc = pcom;
          connect(this, &MotorControl::readShortState, ifc, &IPR112Control::ssPR112ReadShortState, Qt::ConnectionType::BlockingQueuedConnection);
          
          K Offline
          K Offline
          kain
          wrote on 2 Jan 2019, 16:34 last edited by
          #4

          @Christian-Ehrlicher no, since pcom gets already injected as IPR112Control. That connect would also fail since IPR112Control does not inherit from QObject.

          1 Reply Last reply
          0
          • C Christian Ehrlicher
            2 Jan 2019, 15:59

            Wouldn't a simple cast to IPR112Control help here?

            IPR112Control *ifc = pcom;
            connect(this, &MotorControl::readShortState, ifc, &IPR112Control::ssPR112ReadShortState, Qt::ConnectionType::BlockingQueuedConnection);
            
            V Offline
            V Offline
            VRonin
            wrote on 2 Jan 2019, 16:39 last edited by
            #5

            @Christian-Ehrlicher the problem is the 3rd argument (receiver/context), not the slot, I think

            "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
            0
            • K Offline
              K Offline
              kain
              wrote on 2 Jan 2019, 16:50 last edited by
              #6

              Yes, but i already hat pcom of type IPR112Control but you were right with the 3rd argument.
              I did solve the problem now with a dynamic cast and using the old connection-syntax

              connect(this, SIGNAL(readShortState(STATE, int)), dynamic_cast<QObject*>(this->pcom), SLOT(ssPR112ReadShortState(STATE, int)));
              

              This way I lose the compile time checking but this seems to be the smallest tradeoff.

              V 1 Reply Last reply 2 Jan 2019, 17:11
              0
              • K kain
                2 Jan 2019, 16:50

                Yes, but i already hat pcom of type IPR112Control but you were right with the 3rd argument.
                I did solve the problem now with a dynamic cast and using the old connection-syntax

                connect(this, SIGNAL(readShortState(STATE, int)), dynamic_cast<QObject*>(this->pcom), SLOT(ssPR112ReadShortState(STATE, int)));
                

                This way I lose the compile time checking but this seems to be the smallest tradeoff.

                V Offline
                V Offline
                VRonin
                wrote on 2 Jan 2019, 17:11 last edited by
                #7

                @kain said in Multiple Inheritance of Interfaces with Slots:

                This way I lose the compile time checking but this seems to be the smallest tradeoff.

                My suggestion above didn't work? I'm surprised dynamic_cast works, it should only accept reinterpret_cast there...

                "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
                0
                • V VRonin
                  2 Jan 2019, 15:15

                  Try changing it to connect(this, &MotorControl::readShortState, this, std::bind(&IPR112Control::ssPR112ReadShortState, this->pcom, std::placeholders::_1, std::placeholders::_2), Qt::ConnectionType::BlockingQueuedConnection);

                  The only problem now is that you need to make sure this->pcom does not get destroyed while there's still a pending slot to be executed and this was destroyed.

                  If that's a problem then save the return of the connect: pcomConnection = QObject::connect(this, &MotorControl::readShortState, this->pcom, std::bind(&IPR112Control::ssPR112ReadShortState,std::placeholders::_1,std::placeholders::_2), Qt::ConnectionType::BlockingQueuedConnection); and then call QObject::disconnect(pcomConnection); before the deletion of this->pcom and replace the deletion with a delayed one:

                  auto pcomToDelete = this->pcom;
                  QTimer::singleShot(0,[pcomToDelete]()->void{delete pcomToDelete;});
                  
                  K Offline
                  K Offline
                  kshegunov
                  Moderators
                  wrote on 2 Jan 2019, 18:31 last edited by kshegunov 1 Feb 2019, 18:33
                  #8

                  @Christian-Ehrlicher said in Multiple Inheritance of Interfaces with Slots:

                  Wouldn't a simple cast to IPR112Control help here?

                  Nope. This will fail the static assertions in QObject::connect.

                  @VRonin said in Multiple Inheritance of Interfaces with Slots:

                  Try changing it to connect(this, &MotorControl::readShortState, this, std::bind(&IPR112Control::ssPR112ReadShortState, this->pcom, std::placeholders::_1, std::placeholders::_2), Qt::ConnectionType::BlockingQueuedConnection);

                  Correct, however second point is moot. In fact you should set the proper context (this is incorrect here):

                  QObject * context = qobject_cast<QObject *>(pcom);
                  QObject::connect(this, &MotorControl::readShortState, context, std::bind(&IPR112Control::ssPR112ReadShortState, pcom, std::placeholders::_1, std::placeholders::_2), Qt::ConnectionType::BlockingQueuedConnection);
                  

                  Now the connection is broken cleanly whenever context (which is pcom) gets destroyed. No additional work's needed.

                  I'm surprised dynamic_cast works, it should only accept reinterpret_cast there...

                  Why? That's the whole reason dynamic_cast exists in the first place - to runtime cast polymorphic types.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  2
                  • C Offline
                    C Offline
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on 2 Jan 2019, 18:35 last edited by
                    #9

                    @kshegunov said in Multiple Inheritance of Interfaces with Slots:

                    Nope. This will fail the static assertions in QObject::connect.

                    Then just use a lambda :)

                    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

                    1/9

                    2 Jan 2019, 15:04

                    • Login

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