簡體   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