Регистрация псевдонимов типов пользовательских MetaType в Qt - PullRequest
2 голосов
/ 17 января 2020

У меня есть простой пользовательский тип 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' (Убедитесь, что 'imu_controller :: data :: GyrReal' зарегистрировано с использованием qRegisterMetaType ().)

для всех XyztReal псевдонимов типов.

Важно: Программа работает, если тип сигналов класса imu_controller::DataController изменен на XyztReal типов!

PS: Я думаю проблема при регистрации типов. Я прочитал qt docs и несколько тем, но не нашел решения или примеров.

1 Ответ

2 голосов
/ 17 января 2020

Насколько я понимаю, аргумент 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 несколько раз, по одному для каждого возможного псевдонима с каждой возможной комбинацией пространств имен.

...