在debug crashes应用程序上调用已注册类中的qmlRegisterType()

时间:2017-01-30 14:27:11

标签: qt qml qtquick2

我想在注册类中使用qmlRegiterType()。我尝试使用此topic中的方法,但每当我尝试在调试模式下运行应用程序时,它会使应用程序崩溃并显示错误

  

在0x0读取访问冲突

qqml.h(235行)内的宏QML_GETTYPENAMES上崩溃。

TestClass.h

class RegisterQmlTest : public QObject
{
    Q_OBJECT
public:
    explicit RegisterQmlTest(QObject *parent = 0);
};

TestClass.cpp

QML_REGISTER(RegisterQmlTest);

RegisterQmlTest::RegisterQmlTest(QObject *parent) : QObject(parent)
{ }

void RegisterQmlTest::foo()
{
    qDebug() << "Foo test";
}

我尝试在Windows上的Qt 5.6.2上编译MSVC2013x64上的应用程序。

2 个答案:

答案 0 :(得分:3)

你并不是唯一发生这种情况的人:https://github.com/benlau/quickflux/issues/7,我相信这可能是由于 static initialization order fiasco

一种解决方案可能是使用Q_COREAPP_STARTUP_FUNCTION来确保对qmlRegisterType的调用不会过早。

您可以在.cpp文件中使用此宏,如下所示:

static void registerMyQmlTypes() {
    qmlRegisterType<MyType>("MyImortUri", 1, 0, "MyType");
}
Q_COREAPP_STARTUP_FUNCTION(registerMyQmlTypes)

答案 1 :(得分:0)

我有完全相同的问题。问题是,在宏调用staticMetaObject的调用时,与您的类关联的qmlRegisterType未初始化。正如this answer中所述(来自同一主题),您在没有宏的情况下会更灵活。我通过为每个自定义类引入一个静态类型来解决这个问题。

appQmlRegister.hpp

#include <functional>

#include <QtQml>
#include <QList>

namespace app {
    namespace Qml {
        namespace Register {

            auto Init() -> void;

            static auto GetList()->QList<std::function<void(void)>>&;

            template <class T>
            struct Type {
                Type() {
                    auto initializer = []() {
                        qmlRegisterType<T>();
                    };

                    GetList().append(initializer);
                }
            };
        }
    }
}

appQmlRegister.cpp

#include "appQmlRegister.hpp"

namespace app {
    namespace Qml {
        namespace Register {

            auto Init() -> void {
                for (auto registerFunc : GetList()) {
                    registerFunc();
                }
            }

            auto GetList()->QList<std::function<void(void)>>& {
                static QList<std::function<void(void)>> List;
                return List;
            }
        }
    }
}

类型app::Qml::Register::Type采用模板参数(自定义类的类型)并将调用包装在lambda中qmlRegisterType。这就是基本概念。您现在可以完全控制何时通过app::Qml::Register::Init()注册所有自定义类型,而不是立即通话。通过在运行时调用该函数但在启动QML引擎之前,您可以确保staticMetaObject已正确初始化,并且您可以安全地注册它们。

这需要在每个自定义类级别上进行一些输入。您必须在要在QML中注册的类的标头中声明一个静态成员:

MyCustomClass.hpp

#include "appQmlRegister.hpp"

namespace app {

    class MyCustomClass : public QObject {
        Q_OBJECT
    private:
        static Qml::Register::Type<MyCustomClass> Register;
        // stuff...
    }
}

然后在.cpp文件中定义它,如下所示:

MyCustomClass.cpp

#include "MyCustomClass.hpp"

namespace app {
    Qml::Register::Type<MyCustomClass> MyCustomClass::Register;
}

这当然可以扩展为支持其他类型的注册,例如注册不可创建的类型,自定义版本/名称等。我在GitHub

上的QML展示/模板项目中实现了这一点。

希望这有帮助!