一般使用自動link (ap load 時自動load)比較方便,因為幾乎和一般的library 一樣,沒有限制,所以整個class 可以export 出來,使用起來沒有限制 (不會因為是dll 而有特殊)。
但是另一種手動Load (ap 呼叫 LoadLibrary( )來load dll)就不一樣了。
要使用dll 裡export 的function ,要一一用GetProcAddress(inst,"functioname") 來取出。
所以,得到的是一個address。這樣,要 export 出 class 真是不可能了。(倒是codegguru有一篇hack...,示範怎麼作..)。
但是,還是有方法的。利用 address 的這個特性,將class 轉成pure function table (也就是都是virtual 的function),讓 ap 呼叫就可以了。
方法大概是這樣:
DLL 的部份:
Calc.h (借用那篇hack的code, 但是方法不一樣喔)..
class CCalcPI可以看到那個CCalcPI (Pure Interface)。就是要讓ap 使用的。
{
public:
virtual int Add(int i,int j)=0;
};
class CCalc : public CCalcPI
{
public:
CCalc ();
int Add(int i,int j);
~CCalc();
private:
int use;
};
dll implement 的部份:
Calc.cpp
#include "stdafx.h"...順便implement一個singletone.
#include "Calc.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
CCalc* inst=0;
CCalcPI* GetCalc()
{
if(inst==0)
inst = new CCalc();
return inst;
}
CCalc::CCalc()
{
use=0;
}
CCalc::~CCalc()
{
}
int CCalc::Add(int i,int j)
{
use++;
return i+j+use;
}
然後是dll 的def file:
Calc.def
LIBRARY "Calc"export 出來的只有將constructor, destructor包裝起來的C function. (因為是singletone,所以destructor不必傳參數)。
EXPORTS
GetCalc
ReleaseCalc
SECTIONS
.shared READ WRITE SHARED
使用:
App 要使用dll 裡的CCalc class,只能由CalcPI介面操作,必且由GetCalc( )取得CCalc class的實體:
CCalcPI *calcp;
HINSTANCE hInst;
hInst = LoadLibrary(L"\\Windows\\Calc.dll");
if(hInst){
typedef CCalcPI* getcalc(void);
getcalc* fgetc= (getcalc*)GetProcAddress(hInst,L"GetCalc");
if(fgetc){
calcp = (*fgetc)();
int r = calcp->Add(1,2);
CString outstr;
outstr.Format(L"%d",r);
MessageBox(outstr);
CCalcPI* cp2=(*fgetc)(); // 看看singletone有沒有效 : by "use" variable
r=cp2->Add(1,2);
outstr.Format(L"%d",r);
MessageBox(outstr);
}
}
很奇怪,如果不是pure virtual class (CCalcPI),而是直接使用CCalc 的話,Linker會complain Add( ) function 找不到。
這一招其實是客戶教的....但是他的sample code把export function 直接放到class中,我不知道要怎麼作..
這一篇有類似的方法(好像更漂亮),但是我照作 link 還是有error。
3 則留言:
因為CCalc是繼承CCalcPI,而CCalcPI內有一個virtual method.所以必須要implement CCalcPI內的virtual method,才可以直接call.要呼叫DLL要特別小心memory mapping,記的有些compiler不suuport thread for DLL. 大概是 linker 方式的差異而已
喔,是這樣呀。
但是我還是不知道為甚麼是pure virtual 才行。
CCalcPI只是一個空模而已,可以稱為interface. 它可以做到多型機制,只要後面繼承他的class具有implement,這是物件導向的繼承和多型觀念.
張貼留言