Emitting with custom types does not work

I am trying to emit a signal with a custom type. The type is declared with Q_DECLARE_METATYPE and registered in qRegisterMetaType .

When I give a signal, I get the following error for the output stream:

Type "MyType" has id: 1024 ; register status: true QObject::connect: Cannot queue arguments of type 'MyType' (Make sure 'MyType' is registered using qRegisterMetaType().) 

The error is reproduced only if a static connection is used (when objects are in different streams or an explicit Qt::QueuedConnection ), and MyType declared inside the namespace.

Code example: MyType.h

 #define SHOW_BUG #ifdef SHOW_BUG namespace NS { struct MyType { int val; }; } Q_DECLARE_METATYPE( NS::MyType ); #else struct MyType { int val; }; Q_DECLARE_METATYPE( MyType ); #endif 

MyClass.h:

 #include "MyType.h" namespace NS { class MyClass : public QObject { Q_OBJECT public: MyClass( QObject *parent = NULL ); ~MyClass(); signals: void sendMyType( const MyType& tt ); public slots: void invokeBug(); void getMyType( const MyType& tt ); }; } 

Myclass.cpp

 #include <QDebug> namespace NS { MyClass::MyClass(QObject *parent) : QObject(parent) { qRegisterMetaType< MyType >(); } MyClass::~MyClass() { } void MyClass::invokeBug() { const int id = qMetaTypeId< MyType >(); const bool test = QMetaType::isRegistered( id ); qDebug() << "Type \"MyType\" has id: " << id << "; register status: " << test; MyType tt; tt.val = 42; emit sendMyType( tt ); } void MyClass::getMyType( MyType const& tt ) { qDebug() << "Slot fired: " << tt.val; } } 

main.cpp

 #include "MyClass.h" int main(int argc, char *argv[]) { QCoreApplication a( argc, argv ); NS::MyClass c1; NS::MyClass c2; QThread thread; thread.start(); c2.moveToThread( &thread ); QObject::connect( &c1, &NS::MyClass::sendMyType, &c2, &NS::MyClass::getMyType ); QTimer::singleShot( 0, &c1, SLOT( invokeBug() ) ); return a.exec(); } 
+6
source share
2 answers

The code below illustrates the failure and solution. It works on both Qt 4 and Qt 5.

 Now we fail QObject::connect: No such signal NS::Object::badSignal(NS::MyType) in ../metatype-21119397/main.cpp:32 Now we succeed Successful slot call 1 
 #include <QCoreApplication> #include <QDebug> namespace NS { struct MyType { int val; MyType() {} MyType(int v) : val(v) {} }; class Object : public QObject { Q_OBJECT public: Q_SIGNAL void goodSignal(const NS::MyType &); Q_SIGNAL void badSignal(const MyType &); Q_SLOT void slot(const NS::MyType & x) { qDebug() << "Successful slot call" << x.val; } }; } Q_DECLARE_METATYPE(NS::MyType) int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); NS::Object src, dst; qRegisterMetaType<NS::MyType>(); qDebug() << "Now we fail"; #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) QObject::connect(&src, &NS::Object::badSignal, &dst, &NS::Object::slot, Qt::QueuedConnection); #else dst.connect(&src, SIGNAL(badSignal(NS::MyType)), SLOT(slot(NS::MyType)), Qt::QueuedConnection); #endif emit src.goodSignal(NS::MyType(1)); qDebug() << "Now we succeed"; #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) QObject::connect(&src, &NS::Object::goodSignal, &dst, &NS::Object::slot, Qt::QueuedConnection); #else dst.connect(&src, SIGNAL(goodSignal(NS::MyType)), SLOT(slot(NS::MyType)), Qt::QueuedConnection); #endif emit src.goodSignal(NS::MyType(1)); return a.exec(); } #include "main.moc" 
+8
source

Got a response from the Qt team. Very strange usecases, but: signals must be declared with a full namespace . This is the moc restriction coming from it, which does not have a full-blown C ++ analyzer.

So this will work:

  class MyObject { ... // correct Q_SIGNAL void sendMyType( const NS::MyType& tt ); }; 

But it will not be:

 namespace NS { ... class MyObject { ... // wrong Q_SIGNAL void sendMyType( const MyType& tt ); }; } 
+9
source

All Articles