How to use the QRemoteObjet class to share data between processes?
-
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 triggedvoid P1Signal(int value)
but it don't.When I hit
F2
on process 2emit remoteObj->repply(1000);
it doesn't triggervirtual 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); }); }
-
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(); }
-
You need to generate your class
.rep
, see https://doc.qt.io/qt-6/qtremoteobjects-repc.html -
You need to generate your class
.rep
, see https://doc.qt.io/qt-6/qtremoteobjects-repc.html@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?
-
@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?
@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 -
@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-71283I 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).
-
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).
@Joeyy
Without a rep file you can try something like thisclass 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(); }
-
@Joeyy
Without a rep file you can try something like thisclass 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(); }
@Cesar Thanks!!! finally some help.
It's working with the string thing, but how to pass astruct
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?
-
@Cesar Thanks!!! finally some help.
It's working with the string thing, but how to pass astruct
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?