2009-01-14 79 views
7

我有一個應用程序和DLL文件中的幾個插件。插件通過導出庫使用來自 應用程序的符號。該應用程序鏈接在幾個靜態庫中,這是大多數符號的來源。只要應用程序使用符號,此工作正常。如果符號沒有在那裏使用,編譯DLL時會出現鏈接器錯誤。使用MSVC強制符號導出

如何強制導出只在插件中使用的符號?

爲了觸發我已經試過像這樣的出口:

class MyClassExporter 
    { 
     MyClass mInstance; 
    public: 
     MyClassExporter() {} 
    }; 
    static MyClassExporter TheMyClassExporter; 

靜態庫提出申請,迫使出口,沒有工作之一。

回覆Greg(謝謝你的回答)並澄清:我想強制導出的類是MyClass(它有__declspec(...)定義,取決於我想導出還是導入) 。 MyClassExport是我試圖強制將未使用的(根據應用程序)符號包含到應用程序中的。我想'觸摸'這些符號,以便鏈接器將它們識別爲已使用並將它們包含到應用程序中,以便它可以將這些符號導出到我的插件中。將靜態庫鏈接到插件不是一種選擇,因爲它們包含將被複制的單例(應用程序和DLL都有自己的靜態變量副本)。

回答

3

你可能想看看__declspec(出口/進口)

#ifdef DLL_EXPORTING 
#define WHDLL __declspec(dllexport) 
#else 
#define WHDLL __declspec(dllimport) 
#endif 

當鏈接靜態模塊插入DLL只會在所使用的代碼帶來的。我從來沒有從靜態庫中導入任何東西來重新導出它。
也許你只需要在編譯靜態庫時將其標記爲可導出的。

但這讓我想起將std容器放入導出的類中,並在msvc中使用一些技巧來導出專用容器的「實例」。模板代碼類似於您的靜態代碼(在我的思想)

例如沒有你的模板代碼不會導出支持類的警告模板 - 這是MSVC具體從我的理解

template class DLL_EXPORTING std::auto_ptr<wxCursor>; 
class DLL_EXPORTING imageButton : public wxWindow 
{ 
    std::auto_ptr<wxCursor> m_Cursor; 
}; 
+0

我需要從靜態庫導入並導出到插件,因爲我有單身人士,如果我將它們鏈接到DLL(DLL和應用程序有自己的靜態變量)會得到重複。你的第一句話解釋了這個問題:我正在尋找一種方法來強制收錄。 – torque 2009-01-15 08:23:47

4

/INCLUDE指令可用於強制MSVC鏈接器包含一個符號。或者,/OPT:NOREF可用於禁止一般去除未使用的符號。

一種常見的方法是創建一個未使用的函數,該函數引用爲您的插件導出的所有對象。那麼你只需要一個單一的/ INCLUDE指令該函數。

+0

試過這個,但沒有奏效 - 符號是否應該「裝飾」?它們是否可以包含名稱空間? – xtofl 2009-01-18 19:52:26

+0

它與/ OPT:NOREF兼容嗎?如果沒有,你可能會有一個不同的問題... – 2009-01-19 20:44:40

2

我嘗試些什麼來解決這個問題是這樣的:

  1. 構建與功能void afunction(int)靜態庫。
  2. 建立一個DLL,鏈接到靜態庫,導出afunction
  3. 使用afunction符號構建一個exe文件。

怎麼樣?由於鏈接器可以被告知使用__declspec(dllexport)指令導出函數,所以dll只需要聲明一個即將導出的符號。

的LIB具有標題「afunction.h」以及含有該功能體伴隨的CPP文件:

// stat/afunction.h 
namespace static_lib { void afunction(int); } 


// stat/afunction.cpp 
#include "afunction.h" 
namespace static_lib { void afunction(int){ } } 

該DLL具有一個包含文件「indirect.h」,包含該函數的所述聲明出口。該DLL具有鏈接時間依賴於靜態庫。 (連接器選項:輸入/附加依賴: 「static_library.lib」)

// dll/indirect.h 
namespace static_lib { 
    __declspec(dllexport) void afunction(int); 
} 

可執行文件只具有間接包含的文件:

#include <dll/indirect.h> 
int main() { static_lib::afunction(1); } 

你猜怎麼着?它編譯,鏈接,甚至運行!

2

的 「使用庫的依賴輸入」 選項會在VS2005的伎倆!

該選項可以在配置屬性 - >鏈接器 - >常規 - >使用庫依賴項輸入下找到。設置爲「true」強制鏈接所有符號&在每個指定爲項目輸入的LIB中聲明的代碼。

您可以執行以下操作以從DLL中導出符號:在庫項目中定義LIB_EXPORTS,並且在DLL項目或DLL客戶端項目中都不會有任何內容。

#ifdef LIB_EXPORTS 
#define DLLAPI __declspec(dllexport) 
#else 
#define DLLAPI __declspec(dllimport) 
#endif 

原因是在編譯DLL項目時不需要#include LIB項目中的任何頭文件;只需將LIB指定爲鏈接器輸入即可。但是,如果您需要使用DLL中的LIB代碼,則需要#define DLLAPI作爲空的宏;將符號設置爲dllexport或dllimport將分別生成錯誤或警告。