2011-06-06 80 views
2

我在visual C++ 2010中有一個項目,其中包含關鍵頭文件中的預處理器指令。實際上,它是ZMQ源代碼。如何在編譯DLL到靜態庫時處理DLL_EXPORT?

該項目通常配置爲一個DLL,所以頭使用DLL_EXPORT的狀態(定義/未定義)。如果該項目被用來編譯一個dll,頭部可以通過這兩個DLL項目或客戶端代碼中使用,由於從zmq.h採取以下設置:

#if defined _WIN32 
# if defined DLL_EXPORT 
#  define ZMQ_EXPORT __declspec(dllexport) 
# else 
#  define ZMQ_EXPORT __declspec(dllimport) 
# endif 

然而,這不支持設置我正在建立一個靜態庫。因此我必須手動修改頭部。 Visual Studio似乎認識到dll項目設置並相應地處理dll_export的定義。有沒有一個符號被視覺工作室認可,對應於靜態庫設置?基本上,我想通過擴展上面代碼片段中使用的方法來處理靜態庫的編譯和使用。

+0

我認爲這不會有幫助; Visual Studio只需要在'_declspec(dllimport)'(用於鏈接到MSVC * .DLL)和空白(用於鏈接到靜態CRT)之間切換。 – Neil 2011-06-06 23:37:04

回答

8

我只想介紹第二個(可選)宏,像ZMQ_STATIC

#if defined(ZMQ_STATIC) 
# define ZMQ_EXPORT 
#elif defined(DLL_EXPORT) 
# define ZMQ_EXPORT __declspec(dllexport) 
#else 
# define ZMQ_EXPORT __declspec(dllimport) 
#endif 

定義說,構建庫作爲靜態庫或消費它作爲一個靜態庫時,當宏觀兩者。

2

__declspec(dllimport)是完全可選的。當您構建DLL時,鏈接器還會創建一個靜態導入庫。

如果您編譯的客戶端代碼沒有__declspec(dllimport),則它與胖靜態庫或靜態導入庫兼容。鏈接器將全力以赴。

所以我建議:

# if defined DLL_EXPORT 
#  define ZMQ_EXPORT __declspec(dllexport) 
# else 
#  define ZMQ_EXPORT extern 
# endif 

由於@vanza所指出的,你需要消除所有的數據出口(你可以平凡包裝他們在訪問函數)。無論如何,你應該這樣做,數據輸出是脆弱的。


注:__declspec(dllimport)結果稍快函數調用,這是靈活運用靜態庫VS在性能上非常小的增加調用DLL之間的權衡。

+0

__declspec(dllimport)僅適用於函數,但不適用於數據導出。 – vanza 2011-06-06 23:36:00

+0

@vanza:你是對的,但是從DLL中導出的數據非常少見。它在其他方面也很脆弱。 – 2011-06-06 23:39:01

+0

dllimport *將函數名f修改爲__imp_f。 dllexport不會更改名稱。因此,要從普通靜態庫中獲取函數f(),並從導入庫中獲取需要__imp_f(由__declspec(dllimport)生成)。所以你的意思是你可以在鏈接一個目標文件時提供普通的靜態和導入庫,並且使用哪一個取決於目標文件。 – Yttrill 2015-09-12 04:57:04