繁体   English   中英

Q_GLOBAL_STATIC如何与插件一起使用?

[英]How to use Q_GLOBAL_STATIC with plugins?

Q_GLOBAL_STATIC如何与插件一起使用? 我想整体使用“全局” QMap,这样我就不必将QMap放在不同的位置并每次都同步。 如我所读,Q_GLOBAL_STATIC应该完成这项工作。

我的Qt项目具有以下结构:

.
+-- common
|   +-- common.pro
|   +-- singleton.h
|   +-- singleton.cpp [contains Q_GLOBAL_STATIC and returns it via instance() static method]
+-- plugins
|   +-- p1
|   |   +-- p1.pro
|   |   +-- ...
|   +-- p2
|   |   +-- p2.pro
|   |   +-- ...
|   +-- plugins.pro [TEMPLATE = subdirs]
+-- app
|   +-- app.pro
|   +-- app.cpp
|   +-- ...
+-- project.pro [TEMPLATE = subdirs]

主要功能(在app.cpp中)是第一个调用单例的地方。 因此,它是在加载插件之前创建并已知的。

目前,我正在考虑编译singleton.o并将生成的目标文件链接到应用程序和插件。 但是如何只编译目标文件呢?

也许我必须将TEMPLATE(在common.pro中)指定为lib? 如果是这样,它应该是共享库还是静态库? 共享库没有代码副本,因此对于所有的单例来说可能需要这样做,对吗?

我的想法是正确的,是否可以仅通过使用Q_GLOBAL_STATIC来在不显式共享指针的情况下让所有人处于单一状态?

可以共享全局静态实例,而并非以您期望的方式共享。

首先,Q_GLOBAL_STATIC只是一个宏,用于创建具有线程安全性的某个类的本地实例。 因此,这基本上是一种理想的做法:

static MyCass *instance() {
    static auto _instance = new MyClass();
    return _instance;
}
#define myGlobalStatic instance()

宏的优点是,您可以保存代码,它是惰性的并且具有线程安全的构造函数和析构函数。 换句话说,使用此宏创建本地实例可以使其在全局范围内安全地使用。

这意味着即使在不同的源文件中具有相同的Q_GLOBAL_STATIC语句,也将存在多个不同的实例,它们的名称均相同,但仅在本地可用。

这也适用于您的具体想法:在singleton.o中将有一个这样的实例-但是,通过将其链接到3个不同的二进制文件(app,p1,p2),您基本上会在每个二进制文件本地创建3个不同的实例(因为链接器将其从目标文件复制到每个文件的二进制文件中)! 因此,不,您当前的想法不会共享该实例。

归档此文件的唯一方法是创建一个包含单个实例的动态链接库,并从中导出一个提供对实例访问权限的getter函数。 将两个插件和应用链接到该库,在运行时,将只有1个单个实例(作为库的一部分),所有3个实例都可以访问。

对于您的项目,这意味着您必须将Common变成一个共享库,并针对它链接应用程序p1和p2。


但是,还有另一种方法可以独立于Q_GLOBAL_STATIC执行此操作。 此想法的唯一要求是,在全局范围内共享的任何内容都在应用程序之外的其他地方定义。 使用QMap是可行的,因为它是Qt5Core库的一部分。

这个想法是要让应用程序和插件可以访问全局实例,而不是使用全局实例,而是将设置方法添加到将实例传递给插件的插件接口中:

class MyPlugin
{
    Q_DISABLE_COPY(MyPlugin)
public:
    MyPlugin() = default;
    virtual ~MyPlugin() = default;

    // This is the important part: have a setup method
    virtual void setup(QMap<QString, int> &globalMap) = 0;
};

现在,您要做的就是每次从您的应用实例化一个新插件时就调用setup程序! 您可以简单地在加载插件的源文件中包含Q_GLOBAL_STATIC,甚至可以使其成为某些顶级类的成员。

现在,它可以使用qApp对实例方法进行一些修改。

/* [singleton.h] */
class Singleton : public QObject {
    /* ... */
};
Q_DECLARE_OPAQUE_POINTER(Singleton *)
Q_DECLARE_METATYPE(Singleton *)

/* [singleton.cpp] */
Singleton * Singleton::instance() {
    static Singleton * __ptr(NULL);
    if (!qApp->property("singletonkey").isValid() && !__ptr) {
        __ptr = ptr_from_macro; // Q_GLOBAL_STATIC pointer
        qApp->setProperty("singletonkey", QVariant::fromValue(__ptr));
    } else if (!__ptr) {
        __ptr = qvariant_cast<Singleton *>(qApp->property("singletonkey"));
    } else if (!qApp->property("singletonkey").isValid()) {
        qApp->setProperty("singletonkey", QVariant::fromValue(__ptr));
    }
    return __ptr;
}

希望这不会导致其他问题🙈

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM