I have a simple custom type XyztReal
and its aliases in my datamodel.h
header file:
#ifndef IMUCONTROLLERDATAMODEL_H
#define IMUCONTROLLERDATAMODEL_H
#include <QMetaType>
namespace imu_controller {
namespace data {
// some code
struct __attribute__((__packed__)) XyztReal {
qreal x ;
qreal y ;
qreal z ;
qreal ts;
};
typedef XyztReal GyrReal;
typedef XyztReal AccReal;
typedef XyztReal MagReal;
void registerTypes();
}
}
Q_DECLARE_METATYPE(imu_controller::data::XyztReal)
#endif // IMUCONTROLLERDATAMODEL_H
and registering function in source datamodel.cpp
:
void registerTypes()
{
qRegisterMetaType<XyztReal>("XyztReal"); // or qRegisterMetaType<XyztReal>();
qRegisterMetaType<GyrReal >("GyrReal" );
qRegisterMetaType<AccReal >("AccReal" );
qRegisterMetaType<MagReal >("MagReal" );
}
So i call this function in proper place in programm and try to connect signals/slots of some objects in different thread like this:
Qt::ConnectionType ct = static_cast<Qt::ConnectionType>(Qt::BlockingQueuedConnection | Qt::UniqueConnection);
connect(data_ctrl, &imu_controller::DataController::gyrRealReady, this, &MainWindow::someSlot, ct);
where signal/slot has imu_controller::data::GyrReal
and imu_controller::data::XyztReal
arguments type respectively, or:
Qt::ConnectionType ct = static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection);
connect(data_ctrl, &imu_controller::DataController::gyrRealReady, this, &MainWindow::onImuGyrRealReceived, ct);
where signal/slot has imu_controller::data::GyrReal
arguments type both, But program does not works and debuger prints:
QObject::connect: Cannot queue arguments of type 'imu_controller::data::GyrReal' (Make sure 'imu_controller::data::GyrReal' is registered using qRegisterMetaType().)
for all XyztReal
aliases types.
Important:
The program works if imu_controller::DataController
class signals type changed to XyztReal
types!
PS: I think the problem at types registering. I read qt docs and several topics but i don't found a solution or any examples.
As far as I understand, the const char * typeName
argument of qRegisterMetaType
is quite necessary here. Also it takes consistency in terms of namespaces.
Say you have this signal in your DataController
class:
signals:
void some_signal(data::AccReal);
Since the class lies in the imu_controller
namespace, you just add the data
namespace before the argument class name.
Now, in your registerTypes
function, it should be registered like this:
qRegisterMetaType<AccReal >("data::AccReal");
In other words, the typeName
string must match exactly the type of the signal argument as it is written there.
It looks like one can register a type more than once, specifying different typenames, i.e.
qRegisterMetaType<AccReal >("AccReal");
qRegisterMetaType<AccReal >("data::AccReal");
qRegisterMetaType<AccReal >("imu_controller::data::AccReal");
Curiously, if you have a
using WhatEver = imu_controller::data::AccReal;
somewhere, then you can have
signals:
void some_signal(WhatEver);
as long as you have
qRegisterMetaType<AccReal >("WhatEver");
To summarize things up, your register function could be like:
QString aliases[] = {"XyztReal", "GyrReal", "AccReal", "MagReal" };
for(auto a : aliases)
{
qRegisterMetaType<XyztReal>(a.toLatin1());
a.prepend("data::");
qRegisterMetaType<XyztReal>(a.toLatin1());
a.prepend("imu_controller::");
qRegisterMetaType<XyztReal>(a.toLatin1());
}
i.e. you can register XyztReal
several times, one for each possible alias with every possible combination of namespaces.