0

I have two classes named IPCBase and DispatchData. Now I want to pass QDataStrean Object drom IPCBase to DispatchData. First I tried to send it directly using Connect Statement. But it is giving error like QDataStream object is not registered in QRegisterMatatype.

edit :: I have refered this link as well

When, where and why use namespace when registering custom types for Qt

So I have done something like

typedef QDataStream* myDataStrem;
Q_DECLARE_METATYPE(myDataStrem)

and then connect statement in another class(DispatchData)

connect(mpThrIPCReceiver, SIGNAL(dispatchReadData(const int&, myDataStrem)),
        this, SLOT(onIPCDataReceived(const int&, myDataStrem)));

onIPCDataReceived Slot

void DispatchData::onIPCDataReceived(const int& msgType, myDataStrem dataReceived)
{

//    dataReceived >> str1;     Here it is giving error
//    qDebug()<<"is"<<str1;

    MemberFuncPointer f = mIPCCommandMapper.value(msgType);
    (this->*f)(*dataReceived);              
 //This is function pointer which will rout it to respective function depending on the Message type.

and then it will come here

void DispatchData::onStartCountingCycle(QDataStream &dataReceived)
{
    int data = 0;
    dataReceived >> data;     //Here it is crashing

    //Giving error like
    //pure virtual method called
    //terminate called without an active exception

    // I have debugged it and here dataReceived is becoming Readonly.
}
Community
  • 1
  • 1
Umang Modi
  • 11
  • 6
  • I can help You, but please provide a functioning example! – Roland Jun 16 '16 at 07:33
  • 1
    It seems you are using threads, which is why it automatically makes your connection a queued connection. In that case you would have to call [`qRegisterMetatype`](http://doc.qt.io/qt-5/qmetatype.html#details) for `QDataStream` as the message you get tells you. But this still seems very odd to me, why are you sending `QDataStream` object across threads? Explain what are you trying to actually do, this seems like an [XY problem](http://xyproblem.info) to me. – thuga Jun 16 '16 at 07:56
  • @thuga There's no need for `qRegisterMetatype` here. – Kuba hasn't forgotten Monica Jun 16 '16 at 19:16
  • @KubaOber True, I just went with the error message he got. – thuga Jun 17 '16 at 06:37

1 Answers1

0

It seems like you're passing around a dangling pointer: the data stream seems to not exist anymore by the time the receiving thread gets to it. Even if you extended its lifetime in the source object, it's a bad idea to pass a raw pointer through signal-slot connections. If the source class might vanish while the receiver thread has a pending slot call, you'll still be using a dangling pointer at the receiver. You'd be best served by passing around a QSharedPointer or std::shared_ptr.

The following works, you can of course use any type in the shared pointer.

#include <QtCore>
#include <cstdio>

struct Class : public QObject {
   Q_SIGNAL void source(QSharedPointer<QTextStream>);
   Q_SLOT void destination(QSharedPointer<QTextStream> stream) {
      *stream << "Hello" << endl;
   }
   Q_OBJECT
};
Q_DECLARE_METATYPE(QSharedPointer<QTextStream>)

int main(int argc, char ** argv) {
   QCoreApplication app{argc, argv};
   Class c;
   c.connect(&c, &Class::source, &c, &Class::destination, Qt::QueuedConnection);
   auto out = QSharedPointer<QTextStream>(new QTextStream(stdout));
   emit c.source(out);
   QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
   *out << "About to exec" << endl;
   return app.exec();
}
#include "main.moc"

Output:

About to exec
Hello

On modern Qt (5.6 at least), you don't need to call qRegisterMetatype in this case.

The same using std::shared_ptr:

// https://github.com/KubaO/stackoverflown/tree/master/questions/datastream-pass-37850584
#include <QtCore>
#include <cstdio>
#include <memory>

struct Class : public QObject {
   Q_SIGNAL void source(std::shared_ptr<QTextStream>);
   Q_SLOT void destination(std::shared_ptr<QTextStream> stream) {
      *stream << "Hello" << endl;
   }
   Q_OBJECT
};
Q_DECLARE_METATYPE(std::shared_ptr<QTextStream>)

int main(int argc, char ** argv) {
   QCoreApplication app{argc, argv};
   Class c;
   c.connect(&c, &Class::source, &c, &Class::destination, Qt::QueuedConnection);
   auto out = std::make_shared<QTextStream>(stdout);
   emit c.source(out);
   QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
   *out << "About to exec" << endl;
   return app.exec();
}
#include "main.moc"
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313