標籤:stl amp include idt 簡單例子 ports table 依賴 std
庫檔案的產生,包括靜態庫lib與動態庫dll,需要改變編譯輸出的產生命令,可以一開始產生對應的庫工程(或者在工程屬性->常規->配置類型更改)。
附基本對應命令:
gcc –c -L |
.o |
Cl /c /link |
.obj |
ar |
.a |
lib |
.lib |
ld |
.o |
link |
.dll |
其中,動態庫dll需要在所輸出的“對象”前添加_declspec(dllexport)聲明。
對於庫的使用,除了需要包含對應的標頭檔,靜態庫需要在檔案中添加#prama comment(lib,"cof.lib")
或者在有以下幾種情況:
1) 相同解決方案下,可在屬性面板“架構與引用”添加靜態庫工程,並”c++”中添加include file即可
2) 在“link”的附加依賴項添加庫的目錄,在“輸入”中使用添加cof.lib(與pragma同)
windows動態庫有兩種使用方式,使用lib匯入庫,二是使用window api
1) lib匯入庫的使用方式與靜態庫同,但是標頭檔中的“對象”最好有_declspec(dllimport)聲明
2) window api不需要標頭檔
匯出類:
1 簡單例子
dllExample.h:
#pragma once #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif extern DLL_API int a; class DLL_API ExportClass { pirvate: int x; public: void foo(); }; |
dllExample.cpp:
#define DLL_EXPORTS #include "dllExample.h" int a = 4; void ExportClass::foo() { //do something... return; } |
不過這種簡單的DLL匯出存在一個限制,如果我們匯出的類中含有非C++基礎類型:
dllExample.h:
#pragma once #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif class DLL_API ExportClass { pirvate: std::string x; //此處的string類型匯出是不安全的 public: void foo(); }; |
我們知道, 對於STL,微軟為每個版本的VS都有不同的實現,VS2008(VC90),VS2010(VC100),VS2013(VC120)。
由於不同的STL的實現,我們不能在不同的版本見直接傳遞std::string, 否則運行期可能出現不可預知的錯誤。
而事實上我們在ExportClass中的std::string x變數是不希望被外部直接使用的,也就是並沒有export的必要,事實上,不建議讓dll向外匯出任何關於非C++基礎類型的定義。
但是由於ExportClass需要向外匯出(因為需要使用foo()函數),應該如何處理這樣的矛盾呢?
對於這樣的問題,我們需要使用C++的抽象類別(其實就是java中的interface概念)來解決:
我們需要:
1. 申明一個只有純虛函數和C++基礎類型的基類,所有需要向外部匯出的定義都包含在該類中。
2. 申明另一個類,繼承該基類。
3. 實現一個返回基類函數指標的getInstance函數,即返回一個衍生類別執行個體的Factory 方法。
4. 在外部代碼中,通過多態機制訪問該類。
dllExample.h:
#pragma once #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif class DLL_API ExportInterface { public: virtual void foo() = 0; }; extern "C" DLL_API ExportInterface* getInstance(); #ifdef DLL_EXPORTS //我們並不需要向外匯出該類的定義,在外部代碼編譯時間,也不需要包含此類的定義。 class ExportClass: public ExportInterface { pirvate: std::string x; //由於外部代碼對此不可見,此處的std::string是安全的。 public: void foo(); //函數體在dllExample.cpp中實現 }; #endif |
dllExample.cpp:
#define DLL_EXPORTS #include "dllExample.h" extern "C" DLL_API ExportInterface* getInstance() { ExportInterface* pInstance = new ExportClass(); return pInstance; } void ExportClass::foo() { //do something... return; } |
呼叫慣例
關於多個庫的嵌套:
§ 靜態庫包含:靜態庫或者動態庫
只需要對其它庫的引用聲明為extern即可,庫的lib檔案不會包含其它庫的具體實現,主要在最終link的應用中包含其它庫。
§ 動態庫包含 :靜態、動態庫
在本身庫的地方應該包含靜態庫Lib,動態庫的匯入庫lib,而後在最終調用本動態庫的地方只需要引入這個庫的匯入即可。不過最終實現應該要有對應的動態庫。
windows產生庫檔案