如何为qmlRegisterSingletonType实现单例提供程序?

时间:2014-08-20 11:18:36

标签: c++ qt qml

我想在QML中使用C ++ Classes作为Singleton实例,并认为我必须使用qmlRegisterSingletonType注册它们。此函数需要一个函数,该函数提供已注册的C ++类的实例。我正在使用最新的Qt 5.3.1和Windows上的MinGW 4.8。

documentation显示以下提供者函数示例:

static QJSValue example_qjsvalue_singletontype_provider(QQmlEngine *engine, 
    QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)

    static int seedValue = 5;
    QJSValue example = scriptEngine->newObject();
    example.setProperty("someProperty", seedValue++);
    return example;
}

我尝试使用它,但是当我在标题中的类范围之外定义这样的函数时,我收到编译器警告,发生在包含相同标题的另一个cpp文件中:

warning: 'QObject* example_qjsvalue_singletontype_provider(QQmlEngine*, 
QJSEngine*)' defined but not used [-Wunused-function]

此外,编写一个单独的提供程序,在从不同的cpp文件调用时返回一个新实例,这是错误的。所以我尝试了一个自己的实现,我使用静态类成员来返回实例:

// mysingleton.h
class MySingleton: public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(MySingleton)
public:
    static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine) {

        Q_UNUSED(engine)
        Q_UNUSED(scriptEngine)

        if(!m_instance)
        {
            m_instance = new MySingleton();
        }
        return m_instance;
    }
    MySingleton(QObject* parent = 0)
        :QObject(parent)
    {}
private:
    static QObject* m_instance;
};

我尝试使用...

注册
qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton", 
MySingleton::qmlInstance);

此解决方案也不起作用,我收到链接器错误:

release/main.o:main.cpp:
(.text$_ZN11MySingleton11qmlInstanceEP10QQmlEngineP9QJSEngine[__ZN11MySingleton11
qmlInstanceEP10QQmlEngineP9QJSEngine]+0x42): undefined reference to 
`MySingleton::m_instance'

使用类成员函数以外的函数提供所需的Singleton实例1)和使用类成员函数的正确解决方案是什么?

为什么示例建议在每次调用提供者函数时创建一个新实例?

3 个答案:

答案 0 :(得分:10)

  

编写单个提供程序时会感觉不对,该提供程序在从不同的cpp文件调用时返回一个新实例。所以我尝试了一个自己的实现,我使用静态类成员来返回实例

从文档引用qmlRegisterSingletonType函数:

  

注意:从单一类型提供程序返回的QObject单例类型实例归QML引擎所有。因此,单例类型提供程序函数应实现为单例工厂。

这意味着单例类型提供程序返回新实例时的这种行为是通过意图完成的,尽管事实上它正如您所指出的那样,乍一看看起来很奇怪。因此,您的类实现应如下所示:

class MySingleton: public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(MySingleton)

    MySingleton() {}

public:
    static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine)
    {
        Q_UNUSED(engine);
        Q_UNUSED(scriptEngine);

        return new MySingleton;
    }
};

此外,您应该使用&符号MySingleton::qmlInstance,因为它是一个成员方法。有关详细信息,请参阅this。然后注册看起来应该如此:

qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton", &MySingleton::qmlInstance);

答案 1 :(得分:1)

问题是(您的第二个示例)您必须初始化m_instance静态成员变量。您可以在mysingleton.cpp文件中执行此操作,例如:

QObject * MySingleton::m_instance = 0;

答案 2 :(得分:-3)

如果你想从c ++中调用这个单例类,请更改行

return new MySingleton;

为:

return new &MySingleton;