在Qt中注册自定义元类型的别名类型

Registering aliases types of custom MetaType in Qt

本文关键字:类型 别名 自定义 Qt 注册      更新时间:2023-10-16

我在datamodel.h头文件中有一个简单的自定义类型XyztReal及其别名:

#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

和源datamodel.cpp中的注册功能:

void registerTypes()
{
qRegisterMetaType<XyztReal>("XyztReal");   // or qRegisterMetaType<XyztReal>();
qRegisterMetaType<GyrReal >("GyrReal" );
qRegisterMetaType<AccReal >("AccReal" );
qRegisterMetaType<MagReal >("MagReal" );
}

所以我在程序的适当位置调用这个函数,并尝试连接不同线程中某些对象的信号/插槽,如下所示:

Qt::ConnectionType ct = static_cast<Qt::ConnectionType>(Qt::BlockingQueuedConnection | Qt::UniqueConnection);
connect(data_ctrl, &imu_controller::DataController::gyrRealReady, this, &MainWindow::someSlot, ct);

其中信号/插槽分别具有imu_controller::data::GyrRealimu_controller::data::XyztReal参数类型,或者:

Qt::ConnectionType ct = static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection);
connect(data_ctrl, &imu_controller::DataController::gyrRealReady, this, &MainWindow::onImuGyrRealReceived, ct);

其中信号/插槽具有imu_controller::data::GyrReal参数类型,但程序不起作用并且调试器打印:

QObject::connect:无法对类型为"imu_controller::d ata::GyrReal"的参数进行排队 (确保 'imu_controller::d ata::GyrReal' 是使用 qRegisterMetaType(( 注册的。

适用于所有XyztReal别名类型。

重要提示:如果类信号类型更改为XyztReal类型imu_controller::DataController程序有效!

PS:我认为类型注册的问题。 我阅读了qt文档和几个主题,但没有找到解决方案或任何示例。

据我了解,qRegisterMetaTypeconst char * typeName论点在这里是非常必要的。此外,它还需要在命名空间方面保持一致性。

假设您在DataController课上有以下信号:

signals:
void some_signal(data::AccReal);

由于类位于imu_controller命名空间中,因此只需在参数类名之前添加data命名空间。

现在,在您的registerTypes函数中,它应该像这样注册:

qRegisterMetaType<AccReal >("data::AccReal");

换句话说,typeName字符串必须与写入其中的信号参数的类型完全匹配。

看起来可以多次注册一个类型,指定不同的类型名称,即

qRegisterMetaType<AccReal >("AccReal");
qRegisterMetaType<AccReal >("data::AccReal");
qRegisterMetaType<AccReal >("imu_controller::data::AccReal");

奇怪的是,如果你有一个

using WhatEver = imu_controller::data::AccReal;

在某个地方,然后你可以拥有

signals:
void some_signal(WhatEver);

只要你有

qRegisterMetaType<AccReal >("WhatEver");

总结一下,您的寄存器函数可能是这样的:

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());
}

即,您可以多次注册XyztReal,每个可能的别名与每个可能的命名空间组合对应一个。