c++ - 在 Qt 中注册自定义 MetaType 的别名类型
问题描述
我的头文件中有一个简单的自定义类型XyztReal
及其别名:datamodel.h
#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::GyrReal
和imu_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::data::GyrReal”类型的参数进行排队(确保使用 qRegisterMetaType() 注册了“imu_controller::data::GyrReal”。)
对于所有XyztReal
别名类型。
重要提示:
如果imu_controller::DataController
类信号类型更改为XyztReal
类型,则程序可以工作!
PS: 我认为类型注册的问题。我阅读了 qt 文档和几个主题,但没有找到解决方案或任何示例。
解决方案
据我了解,这里的const char * typeName
论点qRegisterMetaType
是非常必要的。此外,它在命名空间方面也需要一致性。
假设您在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
多次,为每个可能的别名和命名空间的每种可能组合注册一次。
推荐阅读
- c# - 文件写入:在完成的文件中显示 Unicode 字符?
- google-apps-script - 如何在谷歌应用脚本执行中存储值?
- r - 我应该在我的新笔记本电脑上下载哪个 R 版本
- javascript-objects - 是否有任何js函数函数可以从分页中获取完整数据
- c - C 中的数组初始化是否需要空值检查?C中的数组初始化会失败吗?
- react-native - 水平滚动视图在本机反应中不起作用
- excel - 行和列公式中的索引和匹配近似值不起作用
- python - 用 django 中的 dict 匹配和减去 QuerySet
- mongodb - MongoDB $lookup 聚合导致嵌套数组
- json - 使用 XSLT 将单个 xml 元素转换为 Json 数组的问题