為了便於學習,本系列文章轉載於http://www.cppblog.com/suiaiguo/archive/2009/07/20/90619.html,如果需要轉載,請註明轉載原網址。
前面介紹了怎麼從DLL中匯出函數和變數,實際上匯出類的方法也是大同小異,廢話就不多說了,下面給個簡單例子示範一下,也就不多做解釋了。
DLL標頭檔:
#ifndef _DLL_SAMPLE_H
#define _DLL_SAMPLE_H
// 通過宏來控制是匯入還是匯出
#ifdef _DLL_SAMPLE
#define DLL_SAMPLE_API __declspec(dllexport)
#else
#define DLL_SAMPLE_API __declspec(dllimport)
#endif
// 匯出/匯入變數聲明
DLL_SAMPLE_API class DLLClass
{
public:
void Show();
};
#undef DLL_SAMPLE_API
#endif
DLL實現檔案:
#include "stdafx.h"
#define _DLL_SAMPLE
#ifndef _DLL_SAMPLE_H
#include "DLLSample.h"
#endif
#include "stdio.h"
//APIENTRY聲明DLL函數進入點
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void DLLClass::Show()
{
printf("DLLClass show!");
}
應用程式調用DLL
#include "DLLSample.h"
#pragma comment(lib,"DLLSample.lib")
int main(int argc, char *argv[])
{
DLLClass dc;
dc.Show();
return 0;
}
大家可能發現了,上面我沒有使用模組定義檔案(.def)聲明匯出類也沒有用顯式連結匯入DLL。
用Depends查看前面編譯出來的DLL檔案,會發現裡面匯出了很奇怪的symbol,這是因為C++編譯器在編譯時間會對symbol進行修飾。
這是我從別人那兒轉來的。
網上找了下,發現了C++編譯時間函數名的修飾約定規則
__stdcall呼叫慣例:
1、以"?"標識函數名的開始,後跟函數名;
2、函數名後面以"@@YG"標識參數表的開始,後跟參數表;
3、參數表以代號表示:
X——void,
D——char,
E——unsigned char,
F——short,
H——int,
I——unsigned int,
J——long,
K——unsigned long,
M——float,
N——double,
_N——bool,
....
PA——表示指標,後面的代號表明指標類型,如果相同類型的指標連續出現,以"0"代替,一個"0"代表一次重複;
4、參數表的第一項為該函數的傳回值類型,其後依次為參數的資料類型,指標標識在其所指資料類型前;
5、參數表後以"@Z"標識整個名字的結束,如果該函數無參數,則以"Z"標識結束。
其格式為"?functionname@@YG*****@Z"或?functionname@@YG*XZ,
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z” void Test2() -----“?Test2@@YGXXZ”
__cdecl呼叫慣例:
規則同上面的_stdcall呼叫慣例,只是參數表的開始標識由上面的"@@YG"變為"@@YA"。
__fastcall呼叫慣例:
規則同上面的_stdcall呼叫慣例,只是參數表的開始標識由上面的"@@YG"變為"@@YI"。
VC++對函數的省缺聲明是"__cedcl",將只能被C/C++調用。
雖然因為C++編譯器對symbol進行修飾的原因不能直接用def檔案聲明匯出類和顯式連結,但是可以用另外一種取巧的方式。
在標頭檔中類的聲明中添加一個友元函數:
friend DLLClass* CreatDLLClass();
然後聲明CreatDLLClass()為匯出函數,通過調用該函數返回一個DLLClass類的對象,同樣達到了匯出類的目的。
這樣,就可以用顯式連結來調用CreatDLLClass(),從而得到類對象了。