11

In short, I get following error:

QObject::connect: Cannot queue arguments of type 'cv::Mat'
(Make sure 'cv::Mat' is registered using qRegisterMetaType().)

What I'm trying to do is send a signal containing two cv::Mat images from a QThread to the main thread, so that I can display the output. There's no compile time error, but when I run the program, it gets stuck at a breakpoint in qglobal.h (inline void qt_noop() {}).

I've tried to add Q_DECLARE_METATYPE(cv::Mat) to the code, to no avail. I'm quite suck with what to do now.

code

In a QThread class:

signals:
void sndFlow(cv::Mat &leftEye, cv::Mat &rightEye);

void eyesDriver::run()
{
    forever
    {
        flow->draw(leftEye, rightEye);
        sndFlow(leftEye, rightEye);
    }
}

Capturing in a QObject class:

public slots:
void recFlow(cv::Mat &leftEye, cv::Mat &rightEye);

void myClass::recFlow(cv::Mat &leftEye, cv::Mat &rightEye)
{
    cv::imshow("left", leftEye);
    cv::imshow("rigth", rightEye);
    cv::waitKey(40);
}

In main:

Q_DECLARE_METATYPE(cv::Mat)
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qRegisterMetaType< cv::Mat >("cv::Mat");
    // create objects from QThread and QObject class
    QObject::connect(&qthread, SIGNAL(sndFlow(cv::Mat&,cv::Mat&)),
                     &qobject, SLOT(recFlow(cv::Mat&,cv::Mat&)));
    qthread.start();
    return a.exec();
}

Changing the signal-slot variables to QSharedPointer< cv::Mat > does not work either. Gives the same error:

QObject::connect: Cannot queue arguments of type 'QSharedPointer<cv::Mat>'
(Make sure 'QSharedPointer<cv::Mat>' is registered using qRegisterMetaType().)

WORKS

All right, it seems to work. I've move qRegisterMetaType< cv::Mat >("cv::Mat"); right before the QObject::connect call. However I still have to 'F5' past the breakpoint in qglobal.h, it works afterwards.

I might be wrong, but it seems that the location of qRegisterMetaType is not trivial.

Raf Berkvens
  • 167
  • 1
  • 8
  • To be honest, I think you might have changed something else inadvertedly, because I don't think that the it matters where you call qRegisterMetaType if it's before the first connect. Or wasn't it? – Tamás Szelei Mar 10 '12 at 14:56

1 Answers1

7

You need to call qRegisterMetaType in addition to the macro (or instead of it, depending on your needs). This is necessary for the signals to be able to marshal your data across threads. However, it might be a wiser idea to pass by reference or smart pointer, or raw pointer if you are using the QObject hierarchy to manage the object lifetime.

Checo R
  • 862
  • 14
  • 22
Tamás Szelei
  • 23,169
  • 18
  • 105
  • 180
  • Any idea where I must call that function? Same as with the macro, I currently try them both in the main.cpp file, the macro above the main function, the `qRegisterMetaType` just inside it. That doesn't solve it, so likely I must call that last function somewhere else. – Raf Berkvens Mar 10 '12 at 11:48
  • I think it must be done before calling connect. Make sure that this class has a public default constructor (a parameterless constructor, that is), a public copy constructor and a public destructor. If not, you have to use one of my alternative suggestions or write a custom QObject wrapper around it (but you probably don't need that). – Tamás Szelei Mar 10 '12 at 11:52
  • cv::Mat has all these, yet it won't work yet. I've tried to call by reference or a pointer, but it yields the same problem. What smart pointer do you suggest? I'm unfamiliar with those. – Raf Berkvens Mar 10 '12 at 11:55
  • It must work if you pass by reference, so there is another problem. Can you post the declaration of your signal and slot, and how and where you connect them? – Tamás Szelei Mar 10 '12 at 11:57
  • What is the error you are getting when using reference parameters? – Tamás Szelei Mar 10 '12 at 12:18
  • Still the same, but with cv::Mat&. I'm getting a notification here to move this to a chat, but I don't have enough reputation yet :). – Raf Berkvens Mar 10 '12 at 12:21
  • I don't have any more ideas, and I'm really puzzled why a reference doesn't get marshalled. Maybe try raw pointers or [QSharedPointer](http://qt-project.org/doc/qt-4.8/qsharedpointer.html#details). Just to clarify, you are creating instances of "myclass", not QObject, right? And as a last resort, could you post the code where you are emitting the signal? – Tamás Szelei Mar 10 '12 at 12:41
  • Right, an instance of myclass, not of QObject. On the clarification part; the program jumps to the error before it could be emitted, since the bug occurs at QObject::connect. I'll try to work with `QSharedPointer`. – Raf Berkvens Mar 10 '12 at 12:50