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?

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

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 2 Posters 1.0k 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