问题
I want to use C++ Classes as Singleton instances in QML and figured that I have to register them with qmlRegisterSingletonType. This function requires a function which provides an instance of the registered C++ class. I am using latest Qt 5.3.1 with included MinGW 4.8 on Windows.
The documentation shows the following example of a provider function:
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;
}
I tried to use this, but I get a compiler warning when I define such a function outside of class scope in a header, occurring in another cpp file including the same header:
warning: 'QObject* example_qjsvalue_singletontype_provider(QQmlEngine*,
QJSEngine*)' defined but not used [-Wunused-function]
Furtheron, it just feels wrong to write a singleton provider which returns a new instance when called from different cpp files. So I tried an own implementation where I use a static class member to return the instance:
// 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;
};
I tried to register this using ...
qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton",
MySingleton::qmlInstance);
This solution doesn't work either, I am getting linker errors:
release/main.o:main.cpp:
(.text$_ZN11MySingleton11qmlInstanceEP10QQmlEngineP9QJSEngine[__ZN11MySingleton11
qmlInstanceEP10QQmlEngineP9QJSEngine]+0x42): undefined reference to
`MySingleton::m_instance'
What is the correct solution to provide the required Singleton instance 1) with a function outside of class scope and 2) with a class member function?
Why does the example suggest to create a new instance on every call of the provider function?
回答1:
it just feels wrong to write a singleton provider which returns a new instance when called from different cpp files. So I tried an own implementation where I use a static class member to return the instance
Quote from documentation to qmlRegisterSingletonType function:
NOTE: A QObject singleton type instance returned from a singleton type provider is owned by the QML engine. For this reason, the singleton type provider function should not be implemented as a singleton factory.
It means that such behaviour when singleton type provider returns a new instance is done by intention despite the fact that it, as you have noted, looks weird at first glance. So, your class implementation should look something like below:
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;
}
};
Moreover, you should use ampersand for MySingleton::qmlInstance
since it is a member method. See this for more info. Then registration should look so:
qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton", &MySingleton::qmlInstance);
回答2:
The problem is (your second example) that you have to initialize your m_instance static member variable. You can do it in mysingleton.cpp file, like:
QObject * MySingleton::m_instance = 0;
回答3:
If you want to call this singleton class also from c++ please change the line
return new MySingleton;
to:
return new &MySingleton;
来源:https://stackoverflow.com/questions/25403363/how-to-implement-a-singleton-provider-for-qmlregistersingletontype