我覺得這個問題可能有一個簡單的解決方案,這對我來說並不明顯 - 我有一個配置類,用於存儲從ini文件加載的各種配置選項等。在我的應用程序中,我有一個庫和客戶端,以及2個配置 - 將庫構建爲DLL並使客戶端動態鏈接,或將它們作爲單個二進制構建在一起。那麼如何在庫和客戶端中使用/使用我的配置對象呢?如果我在兩者中都包含配置類定義,我認爲它會因重新定義而給我提供鏈接錯誤。如何設計一個配置工具既可以靜態鏈接也可以動態鏈接?
0
A
回答
0
如果我在兩者中都包含配置類定義,我認爲它會因重新定義而給我提供鏈接錯誤。
不,它不會。 Windows DLL不尊重一個定義規則。基本上,在Windows中,ODR在模塊邊界處停止,即ODR在內內可執行,而在內但不在它們之間。這是不是一件好事是不相關的,就是這樣。所以,你可以在DLL和可執行文件中包含你的配置類的定義。但是,將會有兩個獨立的單例實例(因爲我認爲它是單例類,正如配置類通常那樣),每個模塊都有一個實例。從這個意義上講,它不會是一個真正的單身人士,至少,不是跨模塊。
如果你想要一個真正的模塊單身人士,你將不得不做更多的工作。您有兩種選擇:主從或合併(或「菊花鏈」)。
第一個選項是指定一個模塊(例如,可執行文件)作爲實例化(並保留)單例對象的模塊,然後將指向該實例的指針傳遞給所有「從」模塊,然後通過一個通用接口使用它(因此兩個模塊對於配置類都有相同的聲明,但只有一個模塊創建它並將其傳遞給其他模塊)。這將是這個樣子:
在頭文件 「config_class.h」:
class ConfigClass {
// a bunch of declarations...
public:
static ConfigClass& getInstance(); // the access-point for the singleton.
};
#ifdef MY_LIB_NOW_BUILDING_MASTER
extern "C" __declspec(dllimport) void setConfigClassInstance(ConfigClass* pobj);
#else
extern "C" __declspec(dllexport) void setConfigClassInstance(ConfigClass* pobj);
#endif
在cpp文件 「config_class.cpp」:
#include "config_class.h"
// a bunch of definitions for the config_class member functions.
#ifdef MY_LIB_NOW_BUILDING_MASTER
ConfigClass& ConfigClass::getInstance() {
static ConfigClass instance(/* */);
return instance;
};
#else
static ConfigClass* masterInstance;
void setConfigClassInstance(ConfigClass* pobj) {
masterInstance = pobj;
};
ConfigClass& ConfigClass::getInstance() {
return *masterInstance;
};
#endif
,其中,在上述例如,您可以從主模塊(很可能是主可執行文件)中調用setConfigClassInstance來爲DLL設置配置對象,但要確保DLL在靜態初始化(加載)期間不需要配置類。
第二個選擇是合併或菊花鏈你的單身人士。在這種情況下,每個模塊創建自己的單例實例,然後使用與上面類似的方案,將指針傳遞給彼此的實例,從而將它們合併爲一個實例(交叉鏈接),或者將它們鏈接在一起(例如,像循環鏈表或環形列表),並將呼叫分派給相應的實例。
我認爲對於您的應用程序,第一個選項可能是最簡單的。
N.B .:在非Windows環境下,情況完全不同,以上都不適用。
相關問題
- 1. g ++不能靜態鏈接libmongcxx(r3.0.2)但動態鏈接可以工作
- 2. 動態鏈接到靜態鏈接?
- 3. import =動態鏈接? &include =靜態鏈接?
- 4. SEO:可以動態生成鏈接嗎?
- 5. 創建一個可以弱鏈接的靜態庫
- 6. 如何配置NetBeans以靜態鏈接MinGW C++庫?
- 7. Angular的深層鏈接 - 動態鏈接vs靜態鏈接
- 8. 靜態鏈接一個dylib
- 9. cmake如何部分靜態鏈接,部分動態鏈接?
- 10. 將動態庫鏈接到一個靜態庫(又名預鏈接動態庫)
- 11. 靜態鏈接glibc,但動態使用GCC動態鏈接glibc
- 12. 如何鏈接一個本身與動態庫鏈接的靜態庫?
- 13. 如何配置libxml2的動態鏈接?
- 14. 靜態鏈接的應用程序是否也可鏈接到一些動態庫?
- 15. 如何使一個div可以鏈接?
- 16. 如何設置動態鏈接的branch.io
- 17. 如何靜態鏈接.DLL?
- 18. 如何靜態鏈接libstdC++
- 19. 如何靜態鏈接portaudio?
- 20. 我可以將靜態庫僅與.a文件鏈接,且沒有.xcodeproj鏈接?
- 21. 在靜態導航上動態設置活動鏈接
- 22. 如何設置鏈接以便與動態網段路由
- 23. 我可以將一個框架靜態鏈接到另一個框架嗎?
- 24. OpenSSL鏈接libcrypto.a以靜態方式
- 25. 設計 - 靜態工具類或接口?
- 26. 靜態鏈接庫
- 27. 鏈接靜態stdlib.so
- 28. 靜態鏈接glib2
- 29. gcc靜態鏈接
- 30. 靜態鏈接OpenCV
「如果我在兩者中都包含配置類定義,我認爲它會因重新定義而給我提供鏈接錯誤。」語句是用於靜態鏈接(將dll構建爲a。lib),而不是動態的;我相信你用上面提供的解決方案,同樣會發生。我相信我可以通過預處理器定義的豐富多彩的使用來解決這個問題,但是如果可能的話,我試圖避免使用特定的方法。 – Rollie
@Rollie哦,所以,如果我得到這個權利,讓我們說你有:main.cpp(應用程序代碼),lib.cpp(庫代碼)和config.cpp(配置類代碼)。其中編譯成main.o,lib.o和config.o。然後你建立一個「exe + dll」爲「(main.o,config.o)+(lib.o,config.o)」的版本,然後你想把dll變成一個靜態庫,並且天真地嘗試鏈接(main.o,config.o,lib.o,config.o)並獲得ODR錯誤。解決方案很簡單,只是在構建靜態版本時不要多次鏈接配置代碼。而已。 –