2009-07-07 32 views
5

所以常見的(至少VS 2005點的狀態)的方式來確定出口/進口的DLL是:同一個頭文件爲DLL和靜態庫

#ifdef MY_EXPORTS 
#define MY_API __declspec(dllexport) 
#else 
#define MY_API __declspec(dllimport) 
#endif 

class MY_API MyClass { 
    ... 
}; 

這個偉大的工程,如果我只是在我的構建代碼作爲DLL。但是,我想要使用靜態庫或DLL的選項。現在一個明顯的(但很糟糕的)解決方案是複製所有代碼,刪除'MY_API'定義的DLL。現在看起來更好的方法是命令行切換來定義或不定義DLL的東西。然而,在靜態庫的情況下,'MY_API'應該是什麼?

#ifdef DLL_CONFIG 
    #ifdef MY_EXPORTS 
    #define MY_API __declspec(dllexport) 
    #else 
    #define MY_API __declspec(dllimport) 
    #endif 
#else 
    #define MY_API // What goes here? 
#endif 

class MY_API MyClass { 
    ... 
}; 

假設現在可以做到這一點會不會有問題時,庫中的用戶包括頭文件(即他們將不得不定義「DLL_CONFIG」)?

回答

12

沒有。

將其保留爲#define MY_API並且MY_API的所有實例都將簡單消失。

您可以添加新的構建配置,例如Debug - DLL和Release - DLL,它們可以模擬除#define DLL_CONFIG之外的其他構造。

要克隆配置,請進入配置管理器(如調試/發佈列表框的下拉列表),然後在「活動解決方案配置」下選擇新建。您現在可以將其命名爲「調試 - DLL」並將Copy Settings設置爲Debug,現在需要做的是定義DLL_CONFIG

爲此,請轉到項目屬性 - >配置屬性 - > C/C++ - >預處理器,然後在其中鍵入DLL_CONFIG。您還會看到,這裏定義了諸如NDEBUGWIN32之類的內容。

haffax said,使用項目特定的名稱。我建議是這樣的:

#ifdef THEPROJECT_USE_DLL 
    #ifdef THEPROJECT_BUILDING_PROJECT 
     #define THEPROJECT_API __declspec(dllexport) 
    #else 
     #define THEPROJECT_API __declspec(dllimport) 
    #endif 
#else 
    #define THEPROJECT_API 
#endif 

現在你的DLL的用戶只需#define THEPROJECT_USE_DLL如果他們使用的DLL版本,就像你的「 - DLL」配置有。

3

只需將MY_API定義爲空。像這樣:

#ifdef DLL_CONFIG 
    #ifdef MY_EXPORTS 
    #define MY_API __declspec(dllexport) 
    #else 
    #define MY_API __declspec(dllimport) 
    #endif 
#else 
    #define MY_API 
#endif 

如果是靜態鏈接,則不需要declspec。

如果用戶想將其用作dll,或者如果他們想將其用作靜態庫,則不需要定義它,您的庫的用戶將必須定義DLL_CONFIG。 現在不會有任何問題。這種配置在許多庫中完成。

編輯:當然,您不應該使用MY_EXPORTSDLL_CONFIG這樣的名稱。爲所有宏使用項目特定的前綴,以避免名稱衝突。

1

什麼都不做。不需要特殊的調用約定來鏈接靜態庫。你唯一需要做的就是確保鏈接器與你的.lib鏈接。