通常的DLL導出類方法,一個簡單的例子:java
dllExample.h:安全
1 #pragma once 2 3 #ifdef DLL_EXPORTS 4 #define DLL_API __declspec(dllexport) 5 #else 6 #define DLL_API __declspec(dllimport) 7 #endif 8 9 class DLL_API ExportClass 10 { 11 pirvate: 12 int x; 13 public: 14 void foo(); 15 };
dllExample.cpp:函數
1 #define DLL_EXPORTS 2 #include "dllExample.h" 3 4 void ExportClass::foo() 5 { 6 //do something... 7 return; 8 }
而外部代碼只須要包含頭文件,就會自動導入ExportClass的定義。
編譯時鏈接該DLL對應的lib,運行時提供DLL文件,便可正常運行。spa
不過這種簡單的DLL導出存在一個限制,若是咱們導出的類中含有非C++基礎類型:指針
dllExample.h:code
1 #pragma once 2 3 #ifdef DLL_EXPORTS 4 #define DLL_API __declspec(dllexport) 5 #else 6 #define DLL_API __declspec(dllimport) 7 #endif 8 9 class DLL_API ExportClass 10 { 11 pirvate: 12 std::string x; //此處的string類型導出是不安全的 13 public: 14 void foo(); 15 };
咱們知道, 對於STL,微軟爲每一個版本的VS都有不一樣的實現,VS2008(VC90),VS2010(VC100),VS2013(VC120)。
因爲不一樣的STL的實現,咱們不能在不一樣的版本見直接傳遞std::string, 不然運行期可能出現不可預知的錯誤。
而事實上咱們在ExportClass中的std::string x變量是不但願被外部直接使用的,也就是並無export的必要,事實上,不建議讓dll向外導出任何關於非C++基礎類型的定義。
可是因爲ExportClass須要向外導出(由於須要使用foo()函數),應該如何處理這樣的矛盾呢?blog
對於這樣的問題,咱們須要使用C++的抽象類(其實就是java中的interface概念)來解決:
咱們須要:
1. 申明一個只有純虛函數和C++基礎類型的基類,全部須要向外部導出的定義都包含在該類中。
2. 申明另外一個類,繼承該基類。
3. 實現一個返回基類函數指針的getInstance函數,即返回一個派生類實例的工廠方法。
4. 在外部代碼中,經過多態機制訪問該類。繼承
dllExample.h:get
1 #pragma once 2 3 #ifdef DLL_EXPORTS 4 #define DLL_API __declspec(dllexport) 5 #else 6 #define DLL_API __declspec(dllimport) 7 #endif 8 9 class DLL_API ExportInterface 10 { 11 public: 12 virtual void foo() = 0; 13 }; 14 15 extern "C" DLL_API ExportInterface* getInstance(); 16 17 #ifdef DLL_EXPORTS //咱們並不須要向外導出該類的定義,在外部代碼編譯時,也不須要包含此類的定義。 18 class ExportClass: public ExportInterface 19 { 20 pirvate: 21 std::string x; //因爲外部代碼對此不可見,此處的std::string是安全的。 22 public: 23 void foo(); //函數體在dllExample.cpp中實現 24 }; 25 #endif
dllExample.cpp:string
#define DLL_EXPORTS #include "dllExample.h" extern "C" DLL_API ExportInterface* getInstance() { ExportInterface* pInstance = new ExportClass(); return pInstance; } void ExportClass::foo() { //do something... return; }