淺談Windows中DLL導出類


一般的DLL導出類方法,一個簡單的例子:

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文件,即可正常運行。

 

不過這種簡單的DLL導出存在一個限制,如果我們導出的類中含有非C++基礎類型:

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     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()函數),應該如何處理這樣的矛盾呢?

對於這樣的問題,我們需要使用C++的抽象類(其實就是java中的interface概念)來解決:
我們需要:
1. 申明一個只有純虛函數和C++基礎類型的基類,所有需要向外部導出的定義都包含在該類中。
2. 申明另一個類,繼承該基類。
3. 實現一個返回基類函數指針的getInstance函數,即返回一個派生類實例的工廠方法。
4. 在外部代碼中,通過多態機制訪問該類。

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 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:

#define DLL_EXPORTS
#include "dllExample.h"

extern "C" DLL_API ExportInterface* getInstance()
{
    ExportInterface* pInstance = new ExportClass();
    return pInstance;
}

void ExportClass::foo()
{
    //do something...
    return;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM