[英]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.