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. How to use the QRemoteObjet class to share data between processes?
Forum Updated to NodeBB v4.3 + New Features

How to use the QRemoteObjet class to share data between processes?

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 2 Posters 978 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 Offline
    J Offline
    Joeyy
    wrote on last edited by
    #1

    I'm trying to follow the Qt Remote Objects example found in this doc, but its very confuse.

    init() on process 2 isn't getting called.

    Also, when I emit the signal from process 1 by hitting F2 emit obj->mySignal(1000); process2 should trigged void P1Signal(int value) but it don't.

    When I hit F2 on process 2 emit remoteObj->repply(1000); it doesn't trigger virtual void repplyFromP2(int value) on process 1.

    Whats wrong?

    //process 1

    // p1.h
    #pragma once
    
    class MyObject : public QObject
    {
        Q_OBJECT
    public:
        MyObject(QObject *parent = nullptr) : QObject(parent) {}
        virtual void repplyFromP2(int value)
        {
            qDebug() << "P2 repplied with:" << value;
        }
    signals:
        void mySignal(int value);
    };
    
    class P1 : public QMainWindow
    {
        Q_OBJECT
    public:
        MyObject* obj = nullptr;
        P1(QWidget *parent = nullptr);
    };
    
    // p1.cpp
    #include "p1.h"
    #include <QtRemoteObjects>
    #include <QRemoteObjectRegistry>
    
    P1::P1(QWidget* parent): QMainWindow(parent)
    {
        obj = new MyObject();
        obj->setObjectName("MyObject");
        //QRemoteObjectHost sourceNode(QUrl(QStringLiteral("local:registry")));
        //sourceNode.enableRemoting(obj, QStringLiteral("MyObject"));
    
        QRemoteObjectRegistryHost regNode(QUrl(QStringLiteral("local:registry"))); // create node that hosts registry
        QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:MyObject")), QUrl(QStringLiteral("local:registry"))); // create node that will host source and connect to registry
        srcNode.enableRemoting(obj); // enable remoting of source object
    
        QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this);
        connect(shortcut, &QShortcut::activated, [this]
        {
            emit obj->mySignal(1000);
        });
    }
    

    //process2

    // p2.h
    #include <QtRemoteObjects>
    #include <QRemoteObjectRegistry>
    
    class RemoteObject : public QObject
    {
        Q_OBJECT
    public:
        RemoteObject(QSharedPointer<QRemoteObjectDynamicReplica> ptr) :
            QObject(nullptr), reptr(ptr)
        {
            //connect signal for replica valid changed with signal slot initialization
            connect(reptr.data(), &QRemoteObjectDynamicReplica::initialized, this,
                &RemoteObject::init);
        }
    
    signals:
        // This signal is connected with the function 
        // repplyFromP2 of P1.
        void repply(int value);
    
    public Q_SLOTS:
        // Slot to receive data from P1.
        void P1Signal(int value)
        {
            qDebug() << "received from P1:" << value;
            emit repply(999); // Emit signal to echo data
        }
    
        void init() //Slot to connect signals/slot on replica initialization
        {
           connect(reptr.data(), SIGNAL(mySignal()), this, SLOT(P1Signal()));
           connect(this, SIGNAL(repply(int)),reptr.data(), SLOT(repplyFromP2(int)));
        }
    
    private:
        QSharedPointer<QRemoteObjectDynamicReplica> reptr;// holds reference to replica
     };
    
    class P2 : public QMainWindow
    {
        Q_OBJECT
    public:
        RemoteObject* remoteObj = nullptr;
        P2(QWidget *parent = nullptr);
    };
    
    // p2.cpp
    #include "p2.h"
    
    P2::P2(QWidget *parent) : QMainWindow(parent)
    {
        QSharedPointer<QRemoteObjectDynamicReplica> ptr; // shared pointer to hold replica
        QRemoteObjectNode repNode;
        repNode.connectToNode(QUrl(QStringLiteral("local:registry")));
        ptr.reset(repNode.acquireDynamic("MyObject")); // acquire replica of source from host node
    
        remoteObj = new RemoteObject(ptr); // create client switch object and pass replica reference to it
    
        QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this);
        connect(shortcut, &QShortcut::activated, [this]
        {
            emit remoteObj->repply(1000);
        });
    }
    
    1 Reply Last reply
    0
    • J Offline
      J Offline
      Joeyy
      wrote on last edited by
      #2

      Could someone give a small example of how to share data between two processes using QRemoteObject?

      1 Reply Last reply
      0
      • J Offline
        J Offline
        Joeyy
        wrote on last edited by
        #3

        I can't get this working, I rewrite it, but the client process does not compile, error:

        Error	C2661	'SharedObject::SharedObject': no overloaded function takes 2 arguments	C:\Qt\6.3.0\qtremoteobjects\src\remoteobjects\qremoteobjectnode.h	78	
        

        //server

        // remoteobject.h
        #include <QRemoteObjectRegistry>
        #include <QRemoteObjectRegistryHost>
        #include <QRemoteObjectHost>
        
        class SharedObject : public QObject
        {
            Q_OBJECT
            Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
        
        public:
            QString text() const { return m_text; }
            void setText(const QString& text)
            {
                if (m_text != text) {
                    m_text = text;
                    emit textChanged(m_text);
                }
            }
        
        signals:
            void textChanged(const QString& text);
        
        private:
            QString m_text;
        };
        
        // main.cpp
        #include "remoteobject.h"
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
        
            SharedObject sharedObject;
            sharedObject.setObjectName("sharedObject");
            QRemoteObjectHost host;
            host.setHostUrl(QUrl("local:sharedObject"));
            host.enableRemoting(&sharedObject);
        
            return a.exec();
        }
        

        //client

        // remoteobject.h
        #include <QRemoteObjectRegistry>
        #include <QRemoteObjectRegistryHost>
        #include <QRemoteObjectHost>
        
        class SharedObject : public QObject
        {
            Q_OBJECT
            Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
        
        public:
            QString text() const { return m_text; }
            void setText(const QString& text)
            {
                if (m_text != text) {
                    m_text = text;
                    emit textChanged(m_text);
                }
            }
        
        signals:
            void textChanged(const QString& text);
        
        private:
            QString m_text;
        };
        
        // main.cpp
        #include "remoteobject.h"
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
        
            QRemoteObjectNode node;
            node.connectToNode(QUrl("local:sharedObject"));
            auto sharedObject = node.acquire<SharedObject>();
        
            QObject::connect(sharedObject, &SharedObject::textChanged, [&](const QString& text) {
                qDebug() << "Text changed to:" << text;
            });
        
            QTimer::singleShot(10000, [&]() {
                qDebug() << "Current text:" << sharedObject->text();
            });
        
            return a.exec();
        }
        
        1 Reply Last reply
        0
        • CesarC Offline
          CesarC Offline
          Cesar
          wrote on last edited by
          #4

          You need to generate your class .rep, see https://doc.qt.io/qt-6/qtremoteobjects-repc.html

          J 1 Reply Last reply
          0
          • CesarC Cesar

            You need to generate your class .rep, see https://doc.qt.io/qt-6/qtremoteobjects-repc.html

            J Offline
            J Offline
            Joeyy
            wrote on last edited by Joeyy
            #5

            @Cesar is not possible to get it working without a .rep file of the class?
            When I add a .rep file to my project Visual Studio doesn't compile anymore
            and it starts causing a lot of weird errors, like not finding files, the log:

            1>Target QtWork:
            1>  repc sharedobject.rep
            1>   repc: D:\p2\sharedobject.rep:1: error: Unknown token encountered
            1>  C:\Users\Local\QtMsBuild\qt_globals.targets(293,5): error MSB4181: The "QtRunWork" task returned false but did not log an error.
            

            Do I need to configure something in VS to be able to compile this rep file?

            CesarC 1 Reply Last reply
            0
            • J Joeyy

              @Cesar is not possible to get it working without a .rep file of the class?
              When I add a .rep file to my project Visual Studio doesn't compile anymore
              and it starts causing a lot of weird errors, like not finding files, the log:

              1>Target QtWork:
              1>  repc sharedobject.rep
              1>   repc: D:\p2\sharedobject.rep:1: error: Unknown token encountered
              1>  C:\Users\Local\QtMsBuild\qt_globals.targets(293,5): error MSB4181: The "QtRunWork" task returned false but did not log an error.
              

              Do I need to configure something in VS to be able to compile this rep file?

              CesarC Offline
              CesarC Offline
              Cesar
              wrote on last edited by
              #6

              @Joeyy said in How to use the QRemoteObjet class to share data between processes?:

              Do I need to configure something in VS to be able to compile this rep file?

              I dont use Visual Studio, so i'm not sure, but searching around, i found this entry:
              https://bugreports.qt.io/browse/QTBUG-71283

              J 1 Reply Last reply
              0
              • CesarC Cesar

                @Joeyy said in How to use the QRemoteObjet class to share data between processes?:

                Do I need to configure something in VS to be able to compile this rep file?

                I dont use Visual Studio, so i'm not sure, but searching around, i found this entry:
                https://bugreports.qt.io/browse/QTBUG-71283

                J Offline
                J Offline
                Joeyy
                wrote on last edited by Joeyy
                #7

                @Cesar

                I think the errors were caused because I added an invalid rep file to the project.
                I could not find how to make VS to auto-generate the rep file, all I could find was this question .

                I tried to use the repc.exe tool, to generate the .rep file, but it also doesn't work:

                C:\Qt\6.3.0\qtbase\bin>repc -i D:/P2/remoteobject.h -o remoteobject.rep
                repc: Unknown input type"D:/P2/remoteobject.h".
                Usage: repc [options] [json-file/rep-file] [rep-file/header-file]
                repc tool v1.0.0 (Qt 6.3.0).
                
                CesarC 1 Reply Last reply
                0
                • J Joeyy

                  @Cesar

                  I think the errors were caused because I added an invalid rep file to the project.
                  I could not find how to make VS to auto-generate the rep file, all I could find was this question .

                  I tried to use the repc.exe tool, to generate the .rep file, but it also doesn't work:

                  C:\Qt\6.3.0\qtbase\bin>repc -i D:/P2/remoteobject.h -o remoteobject.rep
                  repc: Unknown input type"D:/P2/remoteobject.h".
                  Usage: repc [options] [json-file/rep-file] [rep-file/header-file]
                  repc tool v1.0.0 (Qt 6.3.0).
                  
                  CesarC Offline
                  CesarC Offline
                  Cesar
                  wrote on last edited by
                  #8

                  @Joeyy
                  Without a rep file you can try something like this

                  class RemoteObject : public QObject
                  {
                      Q_OBJECT
                      Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
                   public:
                      QString text() const { return m_text; };
                  public slots:
                      void setText(const QString& text)
                      {
                          if (m_text != text) {
                              m_text = text;
                              emit textChanged(m_text);
                          }
                      };
                  
                  signals:
                      void textChanged(const QString& text);
                  private:
                      QString m_text;
                  };
                  
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication a(argc, argv);
                      QRemoteObjectHost host;
                      RemoteObject remoteObject;
                      remoteObject.setObjectName("remoteObject");
                      host.setHostUrl(QUrl("local:remoteObject"));
                      host.enableRemoting(&remoteObject);
                      return a.exec();
                  }
                  

                  and in the client

                  class RemoteObject
                  {
                      Q_OBJECT
                  public:
                      RemoteObject(QString objectName)
                      {
                          repNode.connectToNode(QUrl(QStringLiteral("local:remoteObject")));
                          if (repNode.lastError())
                              qDebug() << "node error:" << repNode.lastError();
                  
                          ptr.reset(repNode.acquireDynamic(objectName));
                  
                          connect(ptr.data(), &QRemoteObjectDynamicReplica::initialized, this, [=]
                          {
                              if (initialized)
                                  return;
                              initialized = true;
                              connect(ptr.data(), SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
                          });
                      }
                  
                      void RemoteObject::text()
                      {
                          QString text = ptr.data()->property("text").toString();
                      }
                  
                      void RemoteObject::setText(const QString& text)
                      {
                          QMetaObject::invokeMethod(ptr.data(), "setText", Q_ARG(QString, text));
                      }
                  
                      void RemoteObject::textChanged(QString text)
                      {
                          qDebug() << "textChanged:" << text;
                      }
                  }
                  
                  int main(int argc, char *argv[])
                  {
                      QApplication a(argc, argv);
                  
                      RemoteObject remoteObject("remoteObject");
                      return a.exec();
                  }
                  
                  J 1 Reply Last reply
                  0
                  • CesarC Cesar

                    @Joeyy
                    Without a rep file you can try something like this

                    class RemoteObject : public QObject
                    {
                        Q_OBJECT
                        Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
                     public:
                        QString text() const { return m_text; };
                    public slots:
                        void setText(const QString& text)
                        {
                            if (m_text != text) {
                                m_text = text;
                                emit textChanged(m_text);
                            }
                        };
                    
                    signals:
                        void textChanged(const QString& text);
                    private:
                        QString m_text;
                    };
                    
                    
                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                        QRemoteObjectHost host;
                        RemoteObject remoteObject;
                        remoteObject.setObjectName("remoteObject");
                        host.setHostUrl(QUrl("local:remoteObject"));
                        host.enableRemoting(&remoteObject);
                        return a.exec();
                    }
                    

                    and in the client

                    class RemoteObject
                    {
                        Q_OBJECT
                    public:
                        RemoteObject(QString objectName)
                        {
                            repNode.connectToNode(QUrl(QStringLiteral("local:remoteObject")));
                            if (repNode.lastError())
                                qDebug() << "node error:" << repNode.lastError();
                    
                            ptr.reset(repNode.acquireDynamic(objectName));
                    
                            connect(ptr.data(), &QRemoteObjectDynamicReplica::initialized, this, [=]
                            {
                                if (initialized)
                                    return;
                                initialized = true;
                                connect(ptr.data(), SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
                            });
                        }
                    
                        void RemoteObject::text()
                        {
                            QString text = ptr.data()->property("text").toString();
                        }
                    
                        void RemoteObject::setText(const QString& text)
                        {
                            QMetaObject::invokeMethod(ptr.data(), "setText", Q_ARG(QString, text));
                        }
                    
                        void RemoteObject::textChanged(QString text)
                        {
                            qDebug() << "textChanged:" << text;
                        }
                    }
                    
                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                    
                        RemoteObject remoteObject("remoteObject");
                        return a.exec();
                    }
                    
                    J Offline
                    J Offline
                    Joeyy
                    wrote on last edited by
                    #9

                    @Cesar Thanks!!! finally some help.
                    It's working with the string thing, but how to pass a struct from the client?
                    I tried to adapt your code:

                    struct MyStruct {
                        int x = 0;
                        QString test;
                    };
                    
                    Q_DECLARE_METATYPE(MyStruct)
                    
                    QDataStream &operator<<(QDataStream &out, const MyStruct &myStruct) {
                        out << myStruct.x;
                        return out;
                    }
                    
                    QDataStream &operator>>(QDataStream &in, MyStruct &myStruct) {
                        in >> myStruct.x;
                        return in;
                    }
                    
                    class RemoteObject : public QObject
                    {
                        Q_OBJECT
                        Q_PROPERTY(WRITE setStruct)
                    public:
                    public slots:
                        void setStruct(MyStruct myStruct) {
                    	qDebug() << "myStruct.x:" << myStruct.x;
                            qDebug() << "myStruct.test:" << myStruct.test;
                        }
                    };
                    
                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                        qRegisterMetaType<MyStruct>("MyStruct");
                        QRemoteObjectHost host;
                        RemoteObject remoteObject;
                        remoteObject.setObjectName("remoteObject");
                        host.setHostUrl(QUrl("local:remoteObject"));
                        host.enableRemoting(&remoteObject);
                        return a.exec();
                    }
                    

                    and on the client:

                    struct MyStruct {
                        int x = 0;
                        QString test;
                    };
                    
                    Q_DECLARE_METATYPE(MyStruct)
                    
                    QDataStream &operator<<(QDataStream &out, const MyStruct &myStruct) {
                        out << myStruct.x;
                        return out;
                    }
                    
                    QDataStream &operator>>(QDataStream &in, MyStruct &myStruct) {
                        in >> myStruct.x;
                        return in;
                    }
                    
                    class RemoteObject
                    {
                        Q_OBJECT
                    public:
                        QSharedPointer<QRemoteObjectDynamicReplica> ptr;
                        QRemoteObjectNode repNode;
                        RemoteObject(QString objectName) {
                            repNode.connectToNode(QUrl(QStringLiteral("local:remoteObject")));
                            ptr.reset(repNode.acquireDynamic(objectName));
                    
                            connect(ptr.data(), &QRemoteObjectDynamicReplica::initialized, this, [=]
                            {
                                qDebug() << "initialized...";
                                MyStruct myStruct;
                                myStruct.x = 1;
                                myStruct.test = "test";
                                setStruct(myStruct);
                            });
                        }
                    
                        void RemoteObject::setStruct(MyStruct myStruct) {
                            QMetaObject::invokeMethod(ptr.data(), "setStruct", myStruct);
                        }
                    }
                    
                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                        qRegisterMetaType<MyStruct>("MyStruct");
                        RemoteObject remoteObject("remoteObject");
                        return a.exec();
                    }
                    

                    But on process 1 when the function setStruct is called i get this error:
                    QVariant::load: unable to load type 65539.
                    and the data in the struct is empty.

                    Whats wrong?

                    CesarC 1 Reply Last reply
                    0
                    • J Joeyy

                      @Cesar Thanks!!! finally some help.
                      It's working with the string thing, but how to pass a struct from the client?
                      I tried to adapt your code:

                      struct MyStruct {
                          int x = 0;
                          QString test;
                      };
                      
                      Q_DECLARE_METATYPE(MyStruct)
                      
                      QDataStream &operator<<(QDataStream &out, const MyStruct &myStruct) {
                          out << myStruct.x;
                          return out;
                      }
                      
                      QDataStream &operator>>(QDataStream &in, MyStruct &myStruct) {
                          in >> myStruct.x;
                          return in;
                      }
                      
                      class RemoteObject : public QObject
                      {
                          Q_OBJECT
                          Q_PROPERTY(WRITE setStruct)
                      public:
                      public slots:
                          void setStruct(MyStruct myStruct) {
                      	qDebug() << "myStruct.x:" << myStruct.x;
                              qDebug() << "myStruct.test:" << myStruct.test;
                          }
                      };
                      
                      int main(int argc, char *argv[])
                      {
                          QApplication a(argc, argv);
                          qRegisterMetaType<MyStruct>("MyStruct");
                          QRemoteObjectHost host;
                          RemoteObject remoteObject;
                          remoteObject.setObjectName("remoteObject");
                          host.setHostUrl(QUrl("local:remoteObject"));
                          host.enableRemoting(&remoteObject);
                          return a.exec();
                      }
                      

                      and on the client:

                      struct MyStruct {
                          int x = 0;
                          QString test;
                      };
                      
                      Q_DECLARE_METATYPE(MyStruct)
                      
                      QDataStream &operator<<(QDataStream &out, const MyStruct &myStruct) {
                          out << myStruct.x;
                          return out;
                      }
                      
                      QDataStream &operator>>(QDataStream &in, MyStruct &myStruct) {
                          in >> myStruct.x;
                          return in;
                      }
                      
                      class RemoteObject
                      {
                          Q_OBJECT
                      public:
                          QSharedPointer<QRemoteObjectDynamicReplica> ptr;
                          QRemoteObjectNode repNode;
                          RemoteObject(QString objectName) {
                              repNode.connectToNode(QUrl(QStringLiteral("local:remoteObject")));
                              ptr.reset(repNode.acquireDynamic(objectName));
                      
                              connect(ptr.data(), &QRemoteObjectDynamicReplica::initialized, this, [=]
                              {
                                  qDebug() << "initialized...";
                                  MyStruct myStruct;
                                  myStruct.x = 1;
                                  myStruct.test = "test";
                                  setStruct(myStruct);
                              });
                          }
                      
                          void RemoteObject::setStruct(MyStruct myStruct) {
                              QMetaObject::invokeMethod(ptr.data(), "setStruct", myStruct);
                          }
                      }
                      
                      int main(int argc, char *argv[])
                      {
                          QApplication a(argc, argv);
                          qRegisterMetaType<MyStruct>("MyStruct");
                          RemoteObject remoteObject("remoteObject");
                          return a.exec();
                      }
                      

                      But on process 1 when the function setStruct is called i get this error:
                      QVariant::load: unable to load type 65539.
                      and the data in the struct is empty.

                      Whats wrong?

                      CesarC Offline
                      CesarC Offline
                      Cesar
                      wrote on last edited by
                      #10

                      You are only deserializing the integer value 'x', but not the QString 'test'.

                      J 1 Reply Last reply
                      0
                      • CesarC Cesar

                        You are only deserializing the integer value 'x', but not the QString 'test'.

                        J Offline
                        J Offline
                        Joeyy
                        wrote on last edited by
                        #11

                        @Cesar i fixed it, but i continue getting the same error.

                        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