Registering aliases types of custom MetaType in Qt

910 views Asked by At

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.

1

There are 1 answers

1
p-a-o-l-o On BEST ANSWER

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.