1、創(chuàng)建win32 dll工程
用VC++6開發(fā)win32 dll是非常方便的,它提供了簡單通用的向?qū)Э梢詾槲覀兩梢粋€(gè)程序框架,而我們只需在在框架里邊加入自己的函數(shù)就可以了,現(xiàn)在就看一下如何生成win32 dll程序。
首先,通過VC++6的AppWizard,創(chuàng)建一個(gè)“Win
然后,在創(chuàng)建類型選擇框中,選擇“An empty Dll project”創(chuàng)建一個(gè)空的dll工程。
2、添加代碼
此時(shí),我們就擁有了一個(gè)Win32dll的工程框架,但這個(gè)工程中什么都沒有,下一步就是在工程中添加代碼了。同樣使用AppWizard創(chuàng)建一個(gè)新的cpp文件dllFile.cpp。當(dāng)然添加文件有多種途徑,但盡量使用程序向?qū)?,因?yàn)樗菍W(xué)習(xí)新方法的最好方法。在文件中加入如下代碼:
#include <windows.h>
BOOL __stdcall DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
Windows.h是編寫windows程序最基本的頭文件,它里面包含了常用的宏及函數(shù)的定義,所以至少得包含它。而DllMain函數(shù)是win32dll的缺省入口函數(shù),每一個(gè)dll中都要有入口函數(shù)。通過入口函數(shù)其它程序在調(diào)用(LoadLibrary)和釋放(FreeLibrary)dll時(shí)對(duì)dll初始化和釋放空間。如果在調(diào)用此dll時(shí)需要分配額外空間,則在此函數(shù)中必須同時(shí)包含分配和釋放空間的代碼,函數(shù)中ul_reason_for_cal參數(shù)表示調(diào)用此函數(shù)的目的??梢栽?/span>DllMain中加入switch表示:
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: //被LoadLibrary調(diào)用
break;
case DLL_THREAD_ATTACH: //創(chuàng)建新線程
break;
case DLL_THREAD_DETACH: //線程退出
break;
case DLL_PROCESS_DETACH: //被FreeLibrary調(diào)用
break;
}
DllMain的一個(gè)參數(shù)hModule表示此dll的句柄,在程序內(nèi)部也可以通過GetModuleFileName函數(shù)獲得它的值。lpReserved參數(shù)是個(gè)保留參數(shù)。DllMain的返回值表示調(diào)用是否成功。至于關(guān)鍵字__stdcall,它是dll函數(shù)的一種定義約定,我們將在后面詳細(xì)講它。到此為止一個(gè)最簡單的win32dll程序就寫好了,如果你覺得至少應(yīng)包含一個(gè)自定義的函數(shù),那我們?cè)偌尤肴缦潞瘮?shù),作用是顯示提示對(duì)話框的函數(shù):
void __stdcall ShowMessage(const LPCTSTR &lpszMsg)
{
MessageBox(NULL,lpszMsg,"MyDll",MB_OK);
}
我們定義ShowMessage函數(shù)為標(biāo)準(zhǔn)調(diào)用方式(__stdcall),在以后的dll函數(shù)的編寫中,我們將都用標(biāo)準(zhǔn)調(diào)用方式。
接下來就需要導(dǎo)出ShowMessage函數(shù)了,只有導(dǎo)出的函數(shù)才能被其它程序調(diào)用,為了避免編譯器修飾函數(shù),我們使用.DEF文件導(dǎo)出函數(shù),工程中添加一個(gè)DllFile.def的文本文件,加入如下代碼:
LIBRARY "MyDll"
EXPORTS
ShowMessage
3.編譯鏈接dll
在VC++中可以通過設(shè)置編譯選項(xiàng)來生成兩種程序版本,一個(gè)是debug版本,另一個(gè)是Release版本。其中debug版本中包含了程序的調(diào)試信息,生成的dll文件一般比較大,但它可以進(jìn)行跟蹤調(diào)試,查看代碼的執(zhí)行過程。雖然dll不能單獨(dú)執(zhí)行,但debug版本的dll在其它程序調(diào)用時(shí)同樣可以跟蹤其中的代碼。而release版本中沒有了附加的調(diào)試信息,文件變小,程序執(zhí)行起來也會(huì)快些。至于快多少,這就看你的整個(gè)程序的代碼的多少和復(fù)雜度了。如果是最終發(fā)布給用戶的程序,那就最好使用了release版本。對(duì)于剛剛編寫好的dll代碼,最好編譯成debug版本,這樣有助于調(diào)試錯(cuò)誤。vc++編譯器默認(rèn)設(shè)置的是debug版本。
你可以通過菜單project->setting設(shè)置每個(gè)版本的編譯選項(xiàng),通過這些選項(xiàng),你能夠控制編譯過程,優(yōu)化程序等等,通常最常用的設(shè)置就是讓編譯器直接把生成的程序放到一個(gè)特定的目錄里,這樣一方面省去在眾多的生成文件中尋找的你的程序文件的麻煩,另一方面,如果你編寫的幾個(gè)程序之間有調(diào)用關(guān)系的話,那么建議在編譯時(shí)就讓它們生成到同一個(gè)目錄中或已確定的目錄中。下面我們把dll的輸出目錄設(shè)置為bin。
不過要注意的是,如果你debug和release版本的輸出目錄設(shè)置為同一個(gè)目錄,那你就得注意別把這兩種版本的生成文件混淆了。
這一切設(shè)置好了,現(xiàn)在你可以編譯程序了,如果順利,那么一個(gè)完整的dll程序“MyDll.dll”就生成了。
使用Visual C++ .NET創(chuàng)建dll
創(chuàng)建win32 dll工程
使用Visual C++ .NET創(chuàng)建dll的過程和Visual C++ 6.0差不多,只是一些命令選項(xiàng)的名稱和位置發(fā)生了變化,比如要?jiǎng)?chuàng)建一個(gè)空win32 dll工程,就需選中win32項(xiàng)目類型中的Win32 項(xiàng)目:
在接下來的應(yīng)用程序向?qū)Т翱谥?,選擇“應(yīng)用程序設(shè)置”頁中的“DLL”,并選中附加選項(xiàng)中的“空項(xiàng)目”就可以了。
添加代碼:
再以后的添加文件和代碼的過程和前面的Visual C++6.0中的完全一樣,完全可以按照前面的方法,編寫代碼。
至于輸出目錄的設(shè)置,你需要執(zhí)行菜單項(xiàng)目->屬性命令,在項(xiàng)目屬性中設(shè)置輸出目錄:
編譯鏈接
就像預(yù)料中的那樣一切ok,接下來我們要通過一個(gè)例子講解如何在應(yīng)用程序中調(diào)用dll并調(diào)試執(zhí)行dll的導(dǎo)出函數(shù)。
1、 在應(yīng)用程序中調(diào)用dll
前面我們已經(jīng)編寫好了一個(gè)dll,接下來我們要看看如何在程序中調(diào)用此dll,其實(shí)調(diào)用方法前面都講過了,現(xiàn)在如何通過導(dǎo)入函數(shù)調(diào)用dll函數(shù)。
首先,我們創(chuàng)建一個(gè)mfc的對(duì)話框應(yīng)用程序,并通過資源編輯器在窗口上添加一個(gè)按鈕,然后在程序文件中添加如下聲明:
__declspec(dllimport) void __stdcall ShowMessage(const LPCTSTR &lpszMsg);
并在按鈕的消息響應(yīng)函數(shù)中使用ShowMessage函數(shù):
ShowMessage(_T("success of calling dll!"));
注意不要忘記了,除了要把MyDll.dll文件復(fù)制到生成的應(yīng)用程序目錄下外,還要把Mydll的導(dǎo)入庫文件復(fù)制到工程目錄下,并把它加入到visaul c++的鏈接庫中:
最后編譯執(zhí)行,點(diǎn)擊窗口上剛剛添加的按鈕,其效果可能就像下圖:
當(dāng)然,也可以不使用導(dǎo)入函數(shù)的方法,而直接使用顯示鏈接的方法調(diào)用dll。那么你可以通過如下方法調(diào)用MyDll.dll,執(zhí)行效果和通過導(dǎo)入函數(shù)的方法無異,并且不需要導(dǎo)入庫的支持:
typedef void (__stdcall *dllfunc)(const LPCTSTR &lpszMsg) ;
HINSTANCE hDll = LoadLibrary(_T("mydll.dll"));
if (NULL != hDll)
{
dllfunc ShowMessage = (dllfunc)GetProcAddress(hDll,_T("ShowMessage"));
if (NULL != ShowMessage)
{
ShowMessage(_T("success of calling dll!"));
}
}
FreeLibrary(hDll);
1、 調(diào)試動(dòng)態(tài)鏈接庫
其實(shí)上面所講的,都是假設(shè)編寫的dll沒有任何錯(cuò)誤,但實(shí)際中,dll中的代碼出現(xiàn)意外錯(cuò)誤也是常有的事,畢竟它和應(yīng)用程序一樣都是由人編寫的,尤其當(dāng)編寫的dll較大時(shí),更需要有辦法跟蹤調(diào)試程序了。但是由于dll不能被單獨(dú)執(zhí)行,當(dāng)我們直接按F5執(zhí)行時(shí)會(huì)出現(xiàn)如下界面:
不能執(zhí)行!在可執(zhí)行應(yīng)用程序中又無法對(duì)dll中的代碼設(shè)斷點(diǎn),那我們?nèi)绾握{(diào)試呢?其實(shí)利用前面我們說的設(shè)置輸出文件目錄的方法,再結(jié)合設(shè)置可執(zhí)行文件就可以實(shí)現(xiàn)在dll工程中調(diào)試dll的目的,而且是一勞永逸的。
1、 首先,設(shè)置dll工程和應(yīng)用程序的輸出目錄設(shè)置到同一目錄中。
2、 然后設(shè)置dll工程中的可執(zhí)行文件路徑和應(yīng)用程序中路徑一樣,比如我們把dll和應(yīng)用程序的可以執(zhí)行文件都輸出到工程外的“bin”目錄中,就如下所示:
1、 最后,你在dll工程中按F5命令執(zhí)行這個(gè)應(yīng)用程序,這時(shí)你就可以像調(diào)試應(yīng)用程序那樣給你的dll代碼設(shè)置斷點(diǎn)并調(diào)試代碼了。
我建議你測試和調(diào)試dll代碼時(shí),同時(shí)開兩個(gè)工程,一個(gè)是dll的,用于設(shè)置斷點(diǎn),察看運(yùn)行過程等等。另一個(gè)是調(diào)用此dll的應(yīng)用程序,在這里隨時(shí)編寫測試代碼,就這么簡單。
聯(lián)系客服