c++qtdllqmetatype

why q_enum unable to get correct type value without qRegisterMetaType?


I have a QT project with several dlls.

Dlls: A, B, C

A depends on B and C. While B and C doesn't have any dependencies.

B exports custom class B_Custom. Class B_Custom is derived from QObject.

Dll A:

Class Exported A : public C
{
    ...
    Q_PROPERTY(B_Custom:B_Enum b_enum READ GetBEnum WRITE SetBEnum NOTIFY BEnumChanged);

    void DoSomething()
    {
        SomethingElse("b_enum");
    }

    ....
}

Dll B:

class Exported B_Custom: public QObject
{
    Q_OBJECT;
    public:
        enum B_Enum {
            ...
        };
        Q_ENUM(B_Enum);
    ...
}

Dll C:

Class C : public QObject
{
    virtual void SomethingElse(const QByteArray &propName)
    {
        auto type = property(propName).userType();
    }
}    

In main:

A * a = new A();
a->DoSomething();

The problem is for Class C, the type value of function SomethingElse is QMetaType::UnknownType.

But if I manually register the B_Enum in Dll B with

qRegisterMetaType<B_Custom::B_Enum>() 

before call A::DoSomething(), the type value of function SomethingElse will not be QMetaType::UnknownType.

It will return correct type value like 1230 for type in function SomethingElse of class C.

But accroding to QT document @http://doc.qt.io/qt-5/qobject.html#Q_ENUM,

Enumerations that are declared with Q_ENUM have their QMetaEnum registered in the enclosing QMetaObject. You can also use QMetaEnum::fromType() to get the QMetaEnum.

Registered enumerations are automatically registered also to the Qt meta type system, making them known to QMetaType without the need to use Q_DECLARE_METATYPE().

So why I need to call qRegisterMetaType() in order to let type in SomethingElse function of Class C get correct type value?

There are quit a lot similar types in dll B and need to get type information in class C.

If I need to use qRegisterMetaType to register these types one by one, its really not a pleasure.


Solution

  • Carefully look into below documentation:

    "Also, to use type T with the QObject::property() API, qRegisterMetaType() must be called before it is used, typically in the constructor of the class that uses T, or in the main() function."

    This is mentioned in http://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1.

    Now coming back to your code:

    you declared Q_ENUM(B_Enum); in class B_Custom.

    But the property for that enum is declared in class A.

    Now again look back to the documentation statement above specified.

    So, to use the enum with the property declared in class A, either you have to register the meta type in the class A constructor or in the main function before using it (which you did and working).

    More over you may get a doubt, why we need to register again in a different class.

    Look into below statement: It seems you have to register the type in all the classes, where ever you are using, not just in the class where you declared.

    "Had the enumeration type been declared in another class, its fully qualified name (i.e., OtherClass::Priority) would be required, and that other class would also have to inherit QObject and register the enumeration type there using the Q_ENUM() macro." (http://doc.qt.io/qt-5/properties.html)