2.dll導出類的幾種方法。
其實我就知道兩種啦,還請大家補充。
先看M$使用的方法。
struct exports{
__declspec(dllexport)exports();
__declspec(dllexport)~exports();
};
exports::exports(){}
exports::~exports(){}
優點:完全和本地的類一樣使用,可以直接new/delete.
缺點:只能使用自動連接(就是連lib的),自由度不高。
不能通過選擇dll的方式來轉換插件(可以通過替換dll文件實現,但是不能保證對所有的修改后的類通用)
繼承exports后沒有辦法通過同一個接口調用子類函數。(因為你永遠new的都是父類,除非重新編譯原來的main程序)
另外一個方法:
這樣聲明exports類:
;//exports.h
struct exports{
friend exports* CreateExports(LPVOID lpparm);
virtual int AddRef();
virtual int Release();//前面講過的方法,如果不清楚請看第一篇delete this
virtual do_sth()=0;//所有成員函數均為虛函數,基類可以純虛。
protected:
exports(){}
virtual ~exports(){}
}
extern "C" CreateExports函數是dll的輸出函數。
編譯exports.cpp成exports.dll
然后在main.cpp:
#include "windows.h"
#include "exports.h"
void main()
{
LoadLibrary("exports");....
PCreateExports=GetProcAddress("CreateExports"....);...
exports* pex=pCreateExports(NULL);
pex->do_sth();
pex->Release();
}
Q:為什么要使用protected的構造函數。
A:因為我不希望exports類被直接使用(這樣就沒有辦法實現多態了,因為new不到子類),所以protected它的構造函數。
這樣在程序里面你只能通過CreateExports來得到Exports類的指針。而CreateExports返回的類是通過lpparm來確定的,這樣就實現了多態性。
Q:為什么要使用delete this 的方法(AddRef/Release)。
A:因為exports類是從dll里面new出來的,所以一定需要在dll里面delete,所以使用這個方法,否則會內存泄漏。
Q:為什么所有成員函數均為虛函數。
A:如果不是虛函數,其實再連接的時候成員函數是會連接代碼到.exe里面去的,這樣就根本call不到dll里面的函數,也就沒有實現我們的原意。
而虛函數是通過函數指針調用的,exports類是再dll里面構造,所以可以保證虛函數是call到dll里面,而且.exe只需要dll的頭文件即可編譯連接通過。
如有缺點、錯誤及遺漏還請大家指教