在qmlRegisterSingletonType中使用非静态方法

Using non-static method in qmlRegisterSingletonType

本文关键字:静态方法 qmlRegisterSingletonType      更新时间:2023-10-16

我正在尝试使用一个非静态方法作为Qt 5中qmlRegisterSingletonType的回调方法。我的代码如下:

PersistentLong couponCounter("couponCounter", handler.getSubjectRunner(), handler.getDbManager());
qmlRegisterSingletonType<PersistentLong>("MyNamespace", 1, 0, "CouponCounter", couponCounter.factory);

但我得到以下编译器错误:

/.../src/Main.cxx: In function ‘int main(int, char**)’:
/.../src/Main.cxx:22:102: error: no matching function for call to ‘qmlRegisterSingletonType(const char [9], int, int, const char [14], <unresolved overloaded function type>)’
     qmlRegisterSingletonType<PersistentLong>("MyNamespace", 1, 0, "CouponCounter", couponCounter.factory);
                                                                                                  ^
/.../src/Main.cxx:22:102: note: candidate is:
In file included from /usr/local/Qt-5.3.2/include/QtQml/QtQml:9:0,
                 from /.../src/Main.cxx:6:
/usr/local/Qt-5.3.2/include/QtQml/qqml.h:476:12: note: template<class T> int qmlRegisterSingletonType(const char*, int, int, const char*, QObject* (*)(QQmlEngine*, QJSEngine*))
 inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName,
            ^
/usr/local/Qt-5.3.2/include/QtQml/qqml.h:476:12: note:   template argument deduction/substitution failed:
/.../src/Main.cxx:22:102: note:   cannot convert ‘couponCounter.PersistentLong::factory’ (type ‘<unresolved overloaded function type>’) to type ‘QObject* (*)(QQmlEngine*, QJSEngine*)’
     qmlRegisterSingletonType<PersistentLong>("MyNamespace", 1, 0, "CouponCounter", couponCounter.factory);

PersistentLongfactory方法如下:

QObject * factory(QQmlEngine *engine, QJSEngine *scriptEngine) {
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)
    return this;
}

问题

关于为什么我不能用这个方法作为qmlRegisterSingletonType的论据,有什么想法吗?

有没有其他方法可以在QML中将非静态实例注册为singleton?

编辑1

couponCounter在main()中以以下方式构建:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QtSubjectHandler handler("burgundy_frontend");
    PersistentLong couponCounter("couponCounter", handler.getSubjectRunner(), handler.getDbManager());
    qmlRegisterSingletonType<PersistentLong>("MyNamespace", 1, 0, "CouponCounter", couponCounter.factory);
}

如果我使用函数指针,我如何在这个函数中引用couponCounter

关于为什么我不能用这个方法作为qmlRegisterSingletonType的论据,有什么想法吗?

考虑到factory方法的使用,我可以猜测它是类的一个成员函数,您正在使用它作为回调。但是,注册功能具有以下签名:

int qmlRegisterSingletonType(const char * uri, int versionMajor, int versionMinor, const char * typeName, QObject *(* ) ( QQmlEngine *, QJSEngine * ) callback)

正如您所看到的,最后一个参数是函数指针,但您(试图)将指针传递给成员函数这是完全不同的。请注意,在这种情况下,friend函数和static函数都不能被利用,因为它们都无法访问this指针。

有没有其他方法可以在QML中将非静态实例注册为singleton?

编写和编译这样的全局函数是完全可行的(static,你在哪里?):

QObject *provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)
    return new MyNiceObject();
}

并像这样注册:

qmlRegisterSingletonType<AppInfo>("AppInfo", 1, 0, "AppInfo", provider);

除了我删除的static之外,Digia示例使用了这种方法。不幸的是,文档非常模糊,并且没有提供使用static修饰符的具体原因,所以我唯一可以考虑的原因是可见性目的。任何更知情/更熟练的人都可以纠正我的错误,并告诉我们是否有更具体的/思考的原因(例如任何特定的内存管理原因)。

最后,重点是为QML引擎提供一个创建我们类型的实例的函数,而这样的结果不能用成员函数来实现。

顺便说一句,如果您更喜欢返回一个singleton实例,您可以利用singleton模式(再次使用static修饰符)并重写如下函数:

 QObject *provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)
    MyNiceObject * p = MyNiceObject::instance();    // uhmmmm static...
    QQmlEngine::setObjectOwnership(p, QQmlEngine::CppOwnership);
    return p;
}

请注意,所创建对象的所有权默认情况下赋予QML引擎。为了避免这个问题,可以使用CCD_ 15调用。