第九講動態(tài)鏈接庫_第1頁
第九講動態(tài)鏈接庫_第2頁
第九講動態(tài)鏈接庫_第3頁
第九講動態(tài)鏈接庫_第4頁
第九講動態(tài)鏈接庫_第5頁
已閱讀5頁,還剩21頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第九講動態(tài)鏈接庫2/6/2023內(nèi)容安排動態(tài)鏈接庫Win32DLL的創(chuàng)建顯式加載方式加載DLLDllMain函數(shù)動態(tài)鏈接庫概述MFCDLL隱式鏈接方式加載DLL2/6/20232動態(tài)鏈接庫概述動態(tài)鏈接庫不能直接運行,不能接收消息。它們是一些獨立的文件,其中包含能被可執(zhí)行程序或其它DLL調(diào)用來完成某項工作的函數(shù)。只有在其它模塊調(diào)用動態(tài)鏈接庫中的函數(shù)時,它才發(fā)揮作用。微軟任何一個版本的Windows操作系統(tǒng),動態(tài)鏈接庫(DLL)都是其核心和基礎(chǔ)。

WindowsAPI中的所有函數(shù)都包含在DLL中。其中有3個最重要的DLL,Kernel32.dll,它包含用于管理內(nèi)存、進程和線程的各個函數(shù);User32.dll,它包含用于執(zhí)行用戶界面任務(wù)(如窗口的創(chuàng)建和消息的傳送)的各個函數(shù);GDI32.dll,它包含用于畫圖和顯示文本的各個函數(shù)。Dll概述2/6/20233動態(tài)鏈接庫概述靜態(tài)庫(LIB)和動態(tài)庫(DLL)

靜態(tài)庫:函數(shù)和數(shù)據(jù)被編譯進一個二進制文件(通常擴展名為.LIB)。在使用靜態(tài)庫的情況下,在編譯鏈接可執(zhí)行文件時,鏈接器從庫中復(fù)制這些函數(shù)和數(shù)據(jù),并把它們和應(yīng)用程序的其它模塊組合起來創(chuàng)建最終的可執(zhí)行文件(.EXE文件)。在使用動態(tài)庫的時候,往往提供兩個文件:一個引入庫和一個DLL。引入庫包含被DLL導(dǎo)出的函數(shù)和變量的符號名,DLL包含實際的函數(shù)和數(shù)據(jù)。在編譯鏈接可執(zhí)行文件時,只需要鏈接引入庫,DLL中的函數(shù)代碼和數(shù)據(jù)并不復(fù)制到可執(zhí)行文件中,在運行的時候,再去加載DLL,訪問DLL中導(dǎo)出的函數(shù)。2/6/20234動態(tài)鏈接庫概述使用動態(tài)鏈接庫的好處增強程序的擴展性可以采用多種編程語言來寫提供二次開發(fā)的平臺簡化項目管理節(jié)省磁盤空間和內(nèi)存有助于資源共享2/6/20235內(nèi)容安排Win32DLL的創(chuàng)建顯式加載方式加載DLLDllMain函數(shù)動態(tài)鏈接庫概述MFCDLL隱式鏈接方式加載DLL動態(tài)鏈接庫2/6/20236Win32DLL的創(chuàng)建創(chuàng)建Dll文件新建一個Win32Dynamic-LinkLibrary工程,在AppWizard的第一步選擇“AnemptyDllproject”,創(chuàng)建一個空的動態(tài)鏈接庫工程。添加一個C++源文件:Dll.cpp,在其中寫入如下代碼:intadd(inta,intb){ returna+b;}intsubtract(inta,intb){ returna-b;}Build后,在Debug目錄下會產(chǎn)生一個Dll1.dll文件。2/6/20237Win32DLL的創(chuàng)建導(dǎo)出DLL中的函數(shù)

注意:應(yīng)用程序如果想要訪問DLL中的函數(shù),那么該函數(shù)必須是已經(jīng)被導(dǎo)出的函數(shù)。為了讓DLL導(dǎo)出函數(shù),需要在每一個將要被導(dǎo)出的函數(shù)前添加標(biāo)識符:_declspec(dllexport)。_declspec(dllexport)intadd(inta,intb){ returna+b;}_declspec(dllexport)intsubtract(inta,intb){ returna-b;}Build后,在Debug目錄下會產(chǎn)生一個動態(tài)庫Dll1.dll文件和一個引入庫文件Dll1.lib。2/6/20238Win32DLL的創(chuàng)建導(dǎo)出DLL中的類在動態(tài)鏈接庫中,除了函數(shù)能被導(dǎo)出,C++類同樣也能夠被導(dǎo)出。為了讓DLL導(dǎo)出類,在DLL中定義類時,需要在class關(guān)鍵字和類名之間加入標(biāo)識符:_declspec(dllexport)。

注意:在訪問導(dǎo)出類的函數(shù)時,仍受限于函數(shù)自身的訪問權(quán)限。也就是說,如果該類的某個函數(shù)訪問權(quán)限不是Pubilc,那么外部程序仍無法訪問這個函數(shù)。另外,在實現(xiàn)動態(tài)鏈接庫時,可以不導(dǎo)出整個類,而只導(dǎo)出該類中的某些成員函數(shù)。具體做法是將標(biāo)識符添加到成員函數(shù)前。2/6/20239內(nèi)容安排Win32Dll

的創(chuàng)建顯式加載方式加載DLLDllMain函數(shù)動態(tài)鏈接庫概述MFCDLL隱式鏈接方式加載DLL動態(tài)鏈接庫2/6/202310隱式鏈接方式加載DLLDLL測試程序新建一個基于對話框的MFC應(yīng)用程序,在主對話框資源上放置兩個按鈕“Add”和“Subtract”,編寫如下響應(yīng)函數(shù):voidCDllTestDlg::OnAdd(){ CStringstr; str.Format("7+5=%d",add(7,5)); MessageBox(str);}voidCDllTestDlg::OnSubtract(){ CStringstr; str.Format("7-5=%d",subtract(7,5)); MessageBox(str);}2/6/202311隱式鏈接方式加載DLLexternintadd(inta,intb);externintsubtract(inta,intb);voidCDllTestDlg::OnAdd(){ CStringstr; str.Format("7+5=%d",add(7,5)); MessageBox(str);}voidCDllTestDlg::OnSubtract(){ CStringstr; str.Format("7-5=%d",subtract(7,5)); MessageBox(str);}利用extern聲明外部函數(shù)以上程序編譯提示兩個錯誤:不認識函數(shù)add與subtract。因此,需對這兩個函數(shù)做一個聲明。

extern

關(guān)鍵字表明函數(shù)是在外部定義的2/6/202312隱式鏈接方式加載DLL以上程序能夠成功通過編譯,但在程序鏈接時會產(chǎn)生三個錯誤,因為此時鏈接器不知道這兩個函數(shù)是在哪個地方實現(xiàn)的。為了解決這個問題,就需要利用動態(tài)鏈接庫的引入庫文件。引入庫文件并沒有包含實際的代碼,它是用來為鏈接程序提供必要的信息,以便在可執(zhí)行文件中建立動態(tài)鏈接時需要用到的重定位表。使用引入庫文件2/6/202313隱式鏈接方式加載DLL加入引入庫的兩種方法加載之前先把dll1.lib復(fù)制到dlltest工程目錄中:方法一:選擇“project\Settings”命令,選擇link選項卡,在“Object/librarymodules”選項編輯框中輸入:dll1.lib方法二:

通過“addfilestoproject…”直接將dll1.lib加入到工程中。2/6/202314隱式鏈接方式加載DLL除了使用extern關(guān)鍵字表明函數(shù)是外部定義的之外,還可以使用標(biāo)識符:_declspec(dllimport)來表明函數(shù)是從動態(tài)鏈接庫中引入的。與使用extern相比,使用_declspec(dllimport)將告訴編譯器該函數(shù)是來源于動態(tài)鏈接庫,從而編譯器可以生成運行效率更高的代碼。利用_declspec(dllimport)聲明外部函數(shù)_declspec(dllimport)intadd(inta,intb);_declspec(dllimport)subtract(inta,intb);2/6/202315隱式鏈接方式加載DLL為查看一個可執(zhí)行模塊依賴的動態(tài)鏈接庫,VisualStudio提供了一個圖形化工具——Depends來實現(xiàn)。位于:“MicrosoftVisualStudio6.0\MicrosoftVisualStudio6.0Tools”菜單中。Depends工具在Depends窗口中,左上方的窗格中顯示了應(yīng)用程序需要訪問的DLL文件名稱;當(dāng)選中其中的一個DLL時,右上方的窗格列出了該DLL中被可執(zhí)行程序調(diào)用的函數(shù);右下方的窗格列出了DLL所導(dǎo)出的函數(shù)。2/6/202316內(nèi)容安排Win32DLL的創(chuàng)建顯式加載方式加載DLLDllMain函數(shù)動態(tài)鏈接庫概述MFCDLL隱式鏈接方式加載DLL動態(tài)鏈接庫2/6/202317顯式加載方式加載DLLLoadLibrary函數(shù)HMODULELoadLibrary(LPCTSTRlpFileName);該函數(shù)的作用是將指定的可執(zhí)行模塊映射到調(diào)用進程的地址空間。LoadLibrary不僅能夠加載DLL,還可以加載可執(zhí)行模塊(*.exe),當(dāng)加載可執(zhí)行模塊時,主要是為了訪問該模塊內(nèi)的資源,例如對話框資源、圖標(biāo)或位圖資源。當(dāng)獲取到動態(tài)鏈接庫模塊的句柄后,接下來需要獲取該動態(tài)鏈接庫中導(dǎo)出函數(shù)的地址。2/6/202318顯式加載方式加載DLLGetProcAddress函數(shù)FARPROCGetProcAddress(HMOUDLEhModule,LPCSTRlpProcName);該函數(shù)的作用是用來獲取DLL導(dǎo)出函數(shù)的地址。hModule:指定DLL模塊的句柄,即LoadLibrary函數(shù)的返回值。LpProcName:字符指針,指定DLL導(dǎo)出函數(shù)的名字或函數(shù)的序號。2/6/202319顯式加載方式加載DLL顯示加載DLL實例voidCDllTestDlg::OnAdd(){ HMODULEhModule; hModule=LoadLibrary("Dll1.dll");

typedefint(*FUNC)(inta,intb);//定義函數(shù)指針類型 FUNCadd=(FUNC)GetProcAddress(hModule,"add"); if(!add) { MessageBox("獲取函數(shù)地址失敗!"); return; } CStringstr; str.Format("7+5=%d",add(7,5)); MessageBox(str);}2/6/202320顯式加載方式加載DLL名字改編問題上述程序運行會談處消息框“獲取函數(shù)地址失??!”,原因如下:C++編譯器在生成DLL時,會對導(dǎo)出的函數(shù)進行名字改編,并且不同的編譯器使用的改編規(guī)則不一樣,因此改編后的名字不一樣的。因此,GetProcAddress的第二個參數(shù)需要寫改編后的函數(shù)名。(改編后的函數(shù)名字可通過Depends工具查到)FUNCadd=(FUNC)GetProcAddress(hModule,"?add@@YAHHH@Z");2/6/202321顯式加載方式加載DLL名字改編問題(續(xù))如果希望動態(tài)鏈接庫在編譯時,導(dǎo)出函數(shù)的名稱不要發(fā)生改變,在定義導(dǎo)出函數(shù)時,需要加上限定符:extern"C"extern"C"_declspec(dllexport)intadd(inta,intb){ returna+b;}extern"C"_declspec(dllexport)intsubtract(inta,intb){ returna-b;}extern“C”可以解決C++對C語言之間的函數(shù)名改編問題,但這種方法有一個缺陷,就是不能用于導(dǎo)出一個類的成員函數(shù),只能用于導(dǎo)出全局函數(shù)這種情況。2/6/202322內(nèi)容安排Win32Dll

的創(chuàng)建顯式加載方式加載DllDllMain函數(shù)動態(tài)鏈接庫概述MFCDll隱式鏈接方式加載Dll動態(tài)鏈接庫2/6/202323DllMain函數(shù)DllMain函數(shù)介紹一個Win32程序,對可執(zhí)行模塊來說,其入口函數(shù)是WinMain;而對DLL來說,其入口函數(shù)是DllMain,該函數(shù)是可選的。也就是說,在編寫DLL程序時,可以提供也可以不提供DllMain函數(shù)。

注意:如果提供了DllMain函數(shù),那么在此函數(shù)中不要進行太復(fù)雜的調(diào)用。因為在加載該動態(tài)鏈接庫時,user32.dll或GDI32.dll等一些Windows核心DLL還沒有

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論