版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
.PAGE.1目錄TOC\o"1-3"\h\u10536目錄111610中文摘要25598Abstract2438一、概論3327571.1.研究背景3271611.2.動(dòng)態(tài)鏈接庫的定義3159921.3.動(dòng)態(tài)鏈接庫與靜態(tài)鏈接庫411931.3.1.靜態(tài)鏈接庫4135941.3.2.動(dòng)態(tài)鏈接庫與靜態(tài)鏈接庫的區(qū)別4296721.4.動(dòng)態(tài)鏈接庫的優(yōu)點(diǎn)4316241.5.在以下這些情況下,必須使用動(dòng)態(tài)鏈接庫: 5151661.6.VisualC++支持的動(dòng)態(tài)鏈接庫的類型520557二、非MFC動(dòng)態(tài)鏈接庫6196472.1.Non-MFCDLL動(dòng)態(tài)鏈接庫的創(chuàng)建6153542.1.1.創(chuàng)建一個(gè)Non-MFCDll工程"MyDll"6149152.1.2.代碼分析8118872.2.聲明導(dǎo)出函數(shù) 9194582.3.DLL的調(diào)用方式 10285312.4.DllMain函數(shù) 114437三、MFC規(guī)則動(dòng)態(tài)鏈接庫的創(chuàng)建13176603.1.概述13256823.2.MFC規(guī)則DLL分為兩類: 1312433.3.MFC規(guī)則DLL的創(chuàng)建 14244033.4.MFC規(guī)則DLL的調(diào)用 18134783.5.隱式調(diào)用2231657四、MFC擴(kuò)展動(dòng)態(tài)鏈接庫的創(chuàng)建24128254.1.概述2428344.3.MFC擴(kuò)展DLL的加載3028477五、動(dòng)態(tài)鏈接庫的典型應(yīng)用3124705.4.DLL木馬3626909六、參考文獻(xiàn)3729778七、致謝38中文摘要?jiǎng)討B(tài)鏈接庫英文為DynamicLinkLibrary,英文縮寫為DLL,是程序運(yùn)行時(shí)由該程序動(dòng)態(tài)鏈接調(diào)用的函數(shù)庫,是一些函數(shù)、數(shù)據(jù)和類集合成的可執(zhí)行模塊,程序員可以將動(dòng)態(tài)鏈接庫動(dòng)態(tài)地集成到自己的程序中以使用庫中的函數(shù)、數(shù)據(jù)和類。開發(fā)和應(yīng)用動(dòng)態(tài)鏈接庫,有助于數(shù)據(jù)和資源的共享,簡(jiǎn)化了軟件項(xiàng)目的管理。本文主要介紹動(dòng)態(tài)鏈接庫創(chuàng)建、調(diào)用方法,及其典型應(yīng)用。關(guān)鍵詞:動(dòng)態(tài)鏈接庫〔DLL,非MFCDLL,MFC規(guī)則DLL,MFC擴(kuò)展DLLAbstractDynamicLinkLibrary<DLL>encapsulatesthesharedresourceandcode.InexploringtheapplicationbasedonWindows,theuseofDLLtechnologycangreatlysavethememory.UsingDLLdevelopingprojectcansimplifytheprojectmanagementandspeeduptheexploration.Thispaper,introducingtheimplicitandexplicitlinkingofDLLwithinstances,providestechnicalsupporttotechniciansinexploringandusingDLL.Keywords:DynamicLinkLibrary<DLL>,Non-MFCDLL,MFCRegularDLL,MFCExtensionDLL一、概論1.1.研究背景自從微軟推出16位的Windows操作系統(tǒng)起,此后每種版本的Windows操作系統(tǒng)都非常依賴于動(dòng)態(tài)鏈接庫<DLL>中的函數(shù)和數(shù)據(jù),實(shí)際上Windows操作系統(tǒng)中幾乎所有的內(nèi)容都由DLL以一種或另外一種形式代表著,例如顯示的字體和圖標(biāo)存儲(chǔ)在GDIDLL中、顯示W(wǎng)indows桌面和處理用戶的輸入所需要的代碼被存儲(chǔ)在一個(gè)UserDLL中、Windows編程所需要的大量的API函數(shù)也被包含在KernelDLL中。在Windows操作系統(tǒng)中使用DLL有很多優(yōu)點(diǎn),最主要的一點(diǎn)是多個(gè)應(yīng)用程序、甚至是不同語言編寫的應(yīng)用程序可以共享一個(gè)DLL文件,真正實(shí)現(xiàn)了資源"共享",大大縮小了應(yīng)用程序的執(zhí)行代碼,更加有效的利用了內(nèi)存;使用DLL的另一個(gè)優(yōu)點(diǎn)是DLL文件作為一個(gè)單獨(dú)的程序模塊,封裝性、獨(dú)立性好,在軟件需要升級(jí)的時(shí)候,開發(fā)人員只需要修改相應(yīng)的DLL文件就可以了,而且,當(dāng)DLL中的函數(shù)改變后,只要不是參數(shù)的改變,程序代碼并不需要重新編譯。這在編程時(shí)十分有用,大大提高了軟件開發(fā)和維護(hù)的效率。既然DLL那么重要,所以搞清楚什么是DLL、如何在Windows操作系統(tǒng)中開發(fā)使用DLL是程序開發(fā)人員不得不解決的一個(gè)問題。本文針對(duì)這些問題,通過一個(gè)簡(jiǎn)單的例子,全面地解析了在VisualC++編譯環(huán)境下編程實(shí)現(xiàn)DLL的過程。1.2.動(dòng)態(tài)鏈接庫的定義動(dòng)態(tài)鏈接庫英文為DynamicLinkLibrary,英文縮寫為DLL,是程序運(yùn)行時(shí)由該程序動(dòng)態(tài)鏈接調(diào)用的函數(shù)庫,是一些函數(shù)、數(shù)據(jù)和類集合成的可執(zhí)行模塊,程序員可以將動(dòng)態(tài)鏈接庫動(dòng)態(tài)地集成到自己的程序中以使用庫中的函數(shù)、數(shù)據(jù)和類。動(dòng)態(tài)鏈接提供了一種方法,使進(jìn)程可以調(diào)用不屬于其可執(zhí)行代碼的函數(shù)。函數(shù)的可執(zhí)行代碼位于一個(gè)DLL中,該DLL包含一個(gè)或多個(gè)已被編譯、鏈接并與使用它們的進(jìn)程分開存儲(chǔ)的函數(shù)。多個(gè)應(yīng)用程序可同時(shí)訪問內(nèi)存中單個(gè)DLL副本的內(nèi)容。1.3.動(dòng)態(tài)鏈接庫與靜態(tài)鏈接庫1.3.1.靜態(tài)鏈接庫靜態(tài)鏈接庫就是你使用的.lib文件,庫中的代碼最后需要連接到你的可執(zhí)行文件中去。靜態(tài)鏈接庫不同于動(dòng)態(tài)鏈接庫〔*.dll,在靜態(tài)庫情況下,函數(shù)和數(shù)據(jù)被編譯進(jìn)一個(gè)二進(jìn)制文件〔通常擴(kuò)展名為*.LIB,VisualC++的編譯器在鏈接過程中將從靜態(tài)庫中恢復(fù)這些函數(shù)和數(shù)據(jù)并把他們和應(yīng)用程序中的其他模塊組合在一起生成可執(zhí)行文件。這個(gè)過程稱為"靜態(tài)鏈接",此時(shí)因?yàn)閼?yīng)用程序所需的全部?jī)?nèi)容都是從庫中復(fù)制了出來,所以靜態(tài)庫本身并不需要與可執(zhí)行文件一起發(fā)行。用戶在交付最終靜態(tài)鏈接庫時(shí),只需要提供.lib文件和相應(yīng)的頭文件,不需要再提供庫的源代碼。在需要使用靜態(tài)庫的工程中,包含相應(yīng)的頭文件,并把.lib文件加入工程中就可以了。1.3.2.動(dòng)態(tài)鏈接庫與靜態(tài)鏈接庫的區(qū)別動(dòng)態(tài)鏈接發(fā)生在程序運(yùn)行時(shí),動(dòng)態(tài)鏈接的函數(shù)代碼不出現(xiàn)在程序的EXE文件中,它僅僅包含了應(yīng)用程序運(yùn)行過程中所調(diào)用的DLL函數(shù)的一些最基本信息〔例如DLL文件位置、函數(shù)名等;而靜態(tài)鏈接發(fā)生在編譯時(shí),靜態(tài)鏈接的函數(shù)代碼實(shí)際被插入到程序的EXE文件中。1.4.動(dòng)態(tài)鏈接庫的優(yōu)點(diǎn)動(dòng)態(tài)鏈接庫隨處可見,無論大型系統(tǒng)還是小規(guī)模軟件,都應(yīng)用了動(dòng)態(tài)鏈接庫,有效地實(shí)現(xiàn)了資源共享。在軟件開發(fā)中,應(yīng)用動(dòng)態(tài)鏈接庫具有以下優(yōu)點(diǎn):〔1擴(kuò)展了應(yīng)用程序的特性;〔2可以用許多種編程語言來編寫;〔3簡(jiǎn)化了軟件項(xiàng)目的管理;〔4有助于節(jié)省內(nèi)存;〔5有助于資源共享;〔6有助于應(yīng)用程序的本地化;〔7有助于解決平臺(tái)差異。1.5.在以下這些情況下,必須使用動(dòng)態(tài)鏈接庫:〔1多個(gè)應(yīng)用程序共享代碼和數(shù)據(jù)〔2在各子程序過濾系統(tǒng)消息時(shí)必須使用動(dòng)態(tài)鏈接庫〔3設(shè)備驅(qū)動(dòng)程序必須是動(dòng)態(tài)鏈接庫〔4在對(duì)話框編輯器中使用自己定義的控件,也必須使用動(dòng)態(tài)鏈接庫〔5為了實(shí)現(xiàn)應(yīng)用程序的國(guó)際化,往往需要使用動(dòng)態(tài)鏈接庫1.6.VisualC++支持的動(dòng)態(tài)鏈接庫的類型VisualC++支持三種DLL,它們分別是Non-MFCDLL〔非MFC動(dòng)態(tài)庫、MFCRegularDLL〔MFC規(guī)則DLL、MFCExtensionDLL〔MFC擴(kuò)展DLL。〔1非MFC動(dòng)態(tài)庫指不使用MFC類庫創(chuàng)建的DLL。Win32DLL中的導(dǎo)出函數(shù)通常使用標(biāo)準(zhǔn)的C接口,這些函數(shù)可以被MFC或非MFC應(yīng)用程序調(diào)用?!?MFC規(guī)則DLLMFC規(guī)則DLL可以使用MFC來創(chuàng)建,可以導(dǎo)出C風(fēng)格的函數(shù),但不能導(dǎo)出C++類、成員函數(shù)或重載函數(shù)。它們可以被MFC或非MFC應(yīng)用程序調(diào)用。但這種類型的DLL不能向應(yīng)用程序傳遞MFC對(duì)象指針,必須使用MFC擴(kuò)展DLL。MFC常規(guī)DLL按照與MFC的鏈接方式又分動(dòng)態(tài)鏈接和靜態(tài)鏈接兩種。〔3MFC擴(kuò)展DLL表面上更像應(yīng)用程序而不像一組函數(shù)的集合,因?yàn)樗梢詣?chuàng)建MFC派生類。只能以動(dòng)態(tài)方式與MFC鏈接,而且只能是使用MFC的動(dòng)態(tài)鏈接版本的應(yīng)用程序才可以使用這種DLL。在MFC擴(kuò)展DLL中,可以由現(xiàn)有的MFC類導(dǎo)出自己的類,然后給應(yīng)用程序一個(gè)擴(kuò)展的MFC版本。支持C++接口,也就是說,該DLL可以導(dǎo)出整個(gè)類,客戶可以構(gòu)造這些類的對(duì)象或從這些類進(jìn)行派生。還可以用于在應(yīng)用程序和DLL之間傳遞MFC導(dǎo)出對(duì)象。對(duì)象的成員函數(shù)位于創(chuàng)建對(duì)象的模塊中,應(yīng)用程序和它加載的擴(kuò)展DLL之間可以自如地傳遞MFC或MFC導(dǎo)出對(duì)象的指針。接下來,我們一起來具體討論一下以上三種動(dòng)態(tài)鏈接庫的創(chuàng)建方法與調(diào)用方法。二、非MFC動(dòng)態(tài)鏈接庫2.1.Non-MFCDLL動(dòng)態(tài)鏈接庫的創(chuàng)建在VisualC++6.0開發(fā)環(huán)境下,打開File/New/Project選項(xiàng),可以選擇Win32Dynamic-LinkLibrary或MFCAppWizard[dll]來以不同的方式來創(chuàng)建Non-MFCDll、RegularDll、ExtensionDll等不同種類的動(dòng)態(tài)鏈接庫。下面演示以Win32Dynamic-LinkLibrary方式創(chuàng)建一個(gè)簡(jiǎn)單Non-MFCDll工程"MyDll"。2.1.1.創(chuàng)建一個(gè)Non-MFCDll工程"MyDll"在VisualC++6.0開發(fā)環(huán)境下,打開File/New/Project選項(xiàng),選擇Win32Dynamic-LinkLibrary創(chuàng)建一個(gè)簡(jiǎn)單DLL工程,并命名為"MyDll"。圖2-1-1創(chuàng)建Non-MFCDll工程"MyDll"在建立的工程中添加lib.h及l(fā)ib.cpp文件,源代碼如下:/*文件名:lib.h*/#ifndefLIB_H#defineLIB_Hextern"C"int__declspec<dllexport>multi<intx,inty>;#endif
/*文件名:lib.cpp*/
#include"lib.h"intmulti<intx,inty>{returnx*y;}顯然,以上建立的是一個(gè)返回兩個(gè)數(shù)的乘積的動(dòng)態(tài)鏈接庫。〔3建立一個(gè)與MyDll工程處于同一工作區(qū)的應(yīng)用工程DllCall。圖2-1-2創(chuàng)建應(yīng)用工程"DllCall"在工程"DllCall"創(chuàng)建源代碼文件"DllCall.cpp",它調(diào)用DLL中的函數(shù)multi,其源代碼如下:#include<stdio.h>#include<windows.h>typedefint<*lpmultiFunc><int,int>;//宏定義函數(shù)指針類型intmain<>{ HINSTANCEhDll;//DLL句柄 lpmultiFuncmultiFunc;//函數(shù)指針 hDll=LoadLibrary<"..\\Debug\\MyDll.dll">; if<hDll!=NULL>{ multiFunc=<lpmultiFunc>GetProcAddress<hDll,"multi">; if<multiFunc!=NULL>{ intresult=multiFunc<3,5>;//計(jì)算3與5的乘積printf<"%d\n",result>;} FreeLibrary<hDll>;} return0;}編譯,運(yùn)行結(jié)果如下:圖2-1-3運(yùn)行結(jié)果如上圖所示,成功返回3*5的結(jié)果,表明此NON-MFCDLL創(chuàng)建成功。2.1.2.代碼分析分析上述代碼,Mydll工程中的lib.h對(duì)函數(shù)multi的聲明前面添加了__declspec<dllexport>語句。這個(gè)語句的含義是聲明函數(shù)multi為DLL的導(dǎo)出函數(shù)。DLL內(nèi)的函數(shù)分為兩種:<1>DLL導(dǎo)出函數(shù),可供應(yīng)用程序調(diào)用;<2>DLL內(nèi)部函數(shù),只能在DLL程序使用,應(yīng)用程序無法調(diào)用它們?,F(xiàn)在分析應(yīng)用工程dllCall對(duì)DLL的調(diào)用是如何實(shí)現(xiàn)的:首先,語句typedefint<*lpmultiFun><int,int>定義了一個(gè)與multi函數(shù)接受參數(shù)類型和返回值均相同的函數(shù)指針類型。隨后,在main函數(shù)中定義了lpmultiFunc的實(shí)例multiFunc;其次,在函數(shù)main中定義了一個(gè)DLLHINSTANCE句柄實(shí)例hDll,通過Win32Api函數(shù)LoadLibrary動(dòng)態(tài)加載了DLL模塊并將DLL模塊句柄賦給了hDll;再次,在函數(shù)main中通過Win32Api函數(shù)GetProcAddress得到了所加載DLL模塊中函數(shù)multi的地址并賦給了multiFunc。經(jīng)由函數(shù)指針multiFunc進(jìn)行了對(duì)DLL中add函數(shù)的調(diào)用;最后,應(yīng)用工程使用完DLL后,在函數(shù)main中通過Win32Api函數(shù)FreeLibrary釋放了已經(jīng)加載的DLL模塊。從而完成了對(duì)dll的調(diào)用。通過以上例子分析可得出以下結(jié)論:<1>DLL中需以某種特定的方式聲明導(dǎo)出函數(shù)〔或變量、類;<2>應(yīng)用工程需以某種特定的方式調(diào)用DLL的導(dǎo)出函數(shù)〔或變量、類。2.2.聲明導(dǎo)出函數(shù)DLL中導(dǎo)出函數(shù)的聲明有兩種方式:一是像上述例子一樣,在定義函數(shù)時(shí)使用導(dǎo)出關(guān)鍵字_declspec<dllexport>;另外一種方法是在創(chuàng)建DLL文件時(shí)使用模塊定義文件.def。如以下例子:下面的代碼演示了怎樣在.def文件中將函數(shù)multi聲明為DLL導(dǎo)出函數(shù)〔需在MyDll工程中添加lib.def文件:LIBRARYMydllEXPORTSmulti1def文件的規(guī)則為:<1>LIBRARY語句說明.def文件相應(yīng)的DLL;<2>EXPORTS語句后列出要導(dǎo)出函數(shù)的名稱??梢栽?def文件中的導(dǎo)出函數(shù)名后加n,表示要導(dǎo)出函數(shù)的序號(hào)為n〔在進(jìn)行函數(shù)調(diào)用時(shí),這個(gè)序號(hào)將發(fā)揮其作用;<3>.def文件中的注釋由每個(gè)注釋行開始處的分號(hào)<;>指定,且注釋不能與語句共享一行。由此可以看出,例子中l(wèi)ib.def文件的含義為生成名為"MyDll"的動(dòng)態(tài)鏈接庫,導(dǎo)出其中的multi函數(shù),并指定multi函數(shù)的序號(hào)為1。2.3.DLL的調(diào)用方式DLL有兩種調(diào)用方式:〔1動(dòng)態(tài)調(diào)用在上述的例子中我們看到了由"LoadLibrary-GetProcAddress-FreeLibrary"系統(tǒng)Api提供的三位一體"DLL加載-DLL函數(shù)地址獲取-DLL釋放"方式,這種調(diào)用方式稱為DLL的動(dòng)態(tài)調(diào)用。
動(dòng)態(tài)調(diào)用方式的特點(diǎn)是完全由編程者用API函數(shù)加載和卸載DLL,程序員可以決定DLL文件何時(shí)加載或不加載,顯式鏈接在運(yùn)行時(shí)決定加載哪個(gè)DLL文件?!?靜態(tài)調(diào)用靜態(tài)調(diào)用方式的特點(diǎn)是由編譯系統(tǒng)完成對(duì)DLL的加載和應(yīng)用程序結(jié)束時(shí)DLL的卸載。當(dāng)調(diào)用某DLL的應(yīng)用程序結(jié)束時(shí),若系統(tǒng)中還有其它程序使用該DLL,則Windows對(duì)DLL的應(yīng)用記錄減1,直到所有使用該DLL的程序都結(jié)束時(shí)才釋放它。靜態(tài)調(diào)用方式簡(jiǎn)單實(shí)用,但不如動(dòng)態(tài)調(diào)用方式靈活。如以下例子所示:將編譯MyDll工程所生成的.lib和.dll文件拷入dllCall工程所在的路徑,圖2-3-1添加MyDll.lib和MyDll.dll文件在dllCall源文件下執(zhí)行下列代碼:#include<stdio.h>#pragmacomment<lib,"MyDll.lib">//.lib文件中僅僅是關(guān)于其對(duì)應(yīng)DLL文件中函數(shù)的重定位信息extern"C"__declspec<dllimport>multi<intx,inty>;intmain<intargc,char*argv[]>
{intresult=multi<3,5>;printf<"靜態(tài)調(diào)用結(jié)果:%d\n",result>;return0;}編譯運(yùn)行,運(yùn)行結(jié)果如下:圖2-3-2運(yùn)行結(jié)果由上述代碼可以看出,靜態(tài)調(diào)用方式的順利進(jìn)行需要完成兩個(gè)動(dòng)作:告訴編譯器與DLL相對(duì)應(yīng)的.lib文件所在的路徑及文件名,#pragmacomment<lib,"MyDll.lib">就是起這個(gè)作用。程序員在建立一個(gè)DLL文件時(shí),連接器會(huì)自動(dòng)為其生成一個(gè)對(duì)應(yīng)的.lib文件,該文件包含了DLL導(dǎo)出函數(shù)的符號(hào)名及序號(hào)〔并不含有實(shí)際的代碼。在應(yīng)用程序里,.lib文件將作為DLL的替代文件參與編譯?!?聲明導(dǎo)入函數(shù),extern"C"__declspec<dllimport>multi<intx,inty>語句中的__declspec<dllimport>發(fā)揮這個(gè)作用。靜態(tài)調(diào)用方式不再需要使用系統(tǒng)API來加載、卸載DLL以及獲取DLL中導(dǎo)出函數(shù)的地址。這是因?yàn)?當(dāng)程序員通過靜態(tài)鏈接方式編譯生成應(yīng)用程序時(shí),應(yīng)用程序中調(diào)用的與.lib文件中導(dǎo)出符號(hào)相匹配的函數(shù)符號(hào)將進(jìn)入到生成的EXE文件中,.lib文件中所包含的與之對(duì)應(yīng)的DLL文件的文件名也被編譯器存儲(chǔ)在EXE文件內(nèi)部。當(dāng)應(yīng)用程序運(yùn)行過程中需要加載DLL文件時(shí),Windows將根據(jù)這些信息發(fā)現(xiàn)并加載DLL,然后通過符號(hào)名實(shí)現(xiàn)對(duì)DLL函數(shù)的動(dòng)態(tài)鏈接。這樣,EXE將能直接通過函數(shù)名調(diào)用DLL的輸出函數(shù),就象調(diào)用程序內(nèi)部的其他函數(shù)一樣。2.4.DllMain函數(shù)Windows在加載DLL的時(shí)候,需要一個(gè)入口函數(shù),就如同控制臺(tái)或DOS程序需要main函數(shù)、WIN32程序需要WinMain函數(shù)一樣。在前面的例子中,DLL并沒有提供DllMain函數(shù),應(yīng)用工程也能成功引用DLL,這是因?yàn)閃indows在找不到DllMain的時(shí)候,系統(tǒng)會(huì)從其它運(yùn)行庫中引入一個(gè)不做任何操作的缺省DllMain函數(shù)版本,并不意味著DLL可以放棄DllMain函數(shù)。根據(jù)編寫規(guī)范,Windows必須查找并執(zhí)行DLL里的DllMain函數(shù)作為加載DLL的依據(jù),它使得DLL得以保留在內(nèi)存里。這個(gè)函數(shù)并不屬于導(dǎo)出函數(shù),而是DLL的內(nèi)部函數(shù)。這意味著不能直接在應(yīng)用工程中引用DllMain函數(shù),DllMain是自動(dòng)被調(diào)用的。以下是一個(gè)DllMain函數(shù)的例子BOOLAPIENTRYDllMain<HANDLEhModule,DWORDul_reason_for_call,LPVOIDlpReserved>
{
switch<ul_reason_for_call>
{
caseDLL_PROCESS_ATTACH:
printf<"\nprocessattachofdll">;
break;
caseDLL_THREAD_ATTACH:
printf<"\nthreadattachofdll">;
break;
caseDLL_THREAD_DETACH:
printf<"\nthreaddetachofdll">;
break;
caseDLL_PROCESS_DETACH:
printf<"\nprocessdetachofdll">;
break;
}
returnTRUE;
}DllMain函數(shù)在DLL被加載和卸載時(shí)被調(diào)用,在單個(gè)線程啟動(dòng)和終止時(shí),DLLMain函數(shù)也被調(diào)用,ul_reason_for_call指明了被調(diào)用的原因。原因共有4種,即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和THREAD_DETACH,以switch語句列出。分析DllMain的函數(shù)頭BOOLAPIENTRYDllMain<HANDLEhModule,WORDul_reason_for_call,LPVOIDlpReserved>APIENTRY被定義為__stdcall,它意味著這個(gè)函數(shù)以標(biāo)準(zhǔn)Pascal的方式進(jìn)行調(diào)用,也就是WINAPI方式;進(jìn)程中的每個(gè)DLL模塊被全局唯一的32字節(jié)的HINSTANCE句柄標(biāo)識(shí),只有在特定的進(jìn)程內(nèi)部有效,句柄代表了DLL模塊在進(jìn)程虛擬空間中的起始地址。在Win32中,HINSTANCE和HMODULE的值是相同的,這兩種類型可以替換使用,這就是函數(shù)參數(shù)hModule的來歷。三、MFC規(guī)則動(dòng)態(tài)鏈接庫的創(chuàng)建3.1.概述〔1MFC規(guī)則DLL,顧名思義,可以在這種DLL的內(nèi)部使用MFC;〔2它是規(guī)則的,意味著它不同于MFC擴(kuò)展DLL,在MFC規(guī)則DLL的內(nèi)部雖然可以使用MFC,但是其與應(yīng)用程序的接口不能是MFC。而MFC擴(kuò)展DLL與應(yīng)用程序的接口可以是MFC,可以從MFC擴(kuò)展DLL中導(dǎo)出一個(gè)MFC類的派生類。MFC規(guī)則DLL能夠被所有支持DLL技術(shù)的語言所編寫的應(yīng)用程序調(diào)用,當(dāng)然也包括使用MFC的應(yīng)用程序。在這種動(dòng)態(tài)連接庫中,包含一個(gè)從CWinApp繼承下來的類,DllMain函數(shù)則由MFC自動(dòng)提供。3.2.MFC規(guī)則DLL分為兩類:〔1靜態(tài)鏈接到MFC的規(guī)則DLL靜態(tài)鏈接到MFC的規(guī)則DLL與MFC庫〔包括MFC擴(kuò)展DLL靜態(tài)鏈接,將MFC庫的代碼直接生成在.dll文件中。在調(diào)用這種DLL的接口時(shí),MFC使用DLL的資源。因此,在靜態(tài)鏈接到MFC的規(guī)則DLL中不需要進(jìn)行模塊狀態(tài)的切換。使用這種方法生成的規(guī)則DLL其程序較大,也可能包含重復(fù)的代碼?!?動(dòng)態(tài)鏈接到MFC的規(guī)則DLL動(dòng)態(tài)鏈接到MFC的規(guī)則DLL可以和使用它的可執(zhí)行文件同時(shí)動(dòng)態(tài)鏈接到MFCDLL和任何MFC擴(kuò)展DLL。在使用了MFC共享庫的時(shí)候,默認(rèn)情況下,MFC使用主應(yīng)用程序的資源句柄來加載資源模板。這樣,當(dāng)DLL和應(yīng)用程序中存在相同ID的資源時(shí)〔即所謂的資源重復(fù)問題,系統(tǒng)可能不能獲得正確的資源。因此,對(duì)于共享MFCDLL的規(guī)則DLL,我們必須進(jìn)行模塊切換以使得MFC能夠找到正確的資源模板。我們可以在VisualC++中設(shè)置MFC規(guī)則DLL是靜態(tài)鏈接到MFCDLL還是動(dòng)態(tài)鏈接到MFCDLL。如下圖,依次選擇VisualC++的project->Settings->General菜單或選項(xiàng),在MicrosoftFoundationClasses中進(jìn)行設(shè)置。圖3-2-1設(shè)置動(dòng)態(tài)/靜態(tài)鏈接MFCDLL3.3.MFC規(guī)則DLL的創(chuàng)建下面一步步講述使用MFC向?qū)?chuàng)建一個(gè)簡(jiǎn)單的MFC規(guī)則DLL的過程。〔1首先在VisualC++6.0開發(fā)環(huán)境下,打開File/New/Project選項(xiàng),選擇MFCAppWizard<dll>創(chuàng)建一個(gè)簡(jiǎn)單DLL工程,并命名為"regularDll"。圖3-3-1創(chuàng)建MFC規(guī)則DLL點(diǎn)擊"確定"進(jìn)入如下圖所示的對(duì)話框,選擇"動(dòng)態(tài)鏈接庫和MFC靜態(tài)鏈接"圖3-3-2創(chuàng)建MFC規(guī)則DLL點(diǎn)擊"完成"按鈕完成向?qū)??!?在工程中添加一個(gè)對(duì)話框,并設(shè)計(jì)該對(duì)話框。圖3-3-3創(chuàng)建對(duì)話框?yàn)樵搶?duì)話框新建一個(gè)類CDllDialog,圖3-3-4新建類CDllDialog為對(duì)話框上的按鈕"MFCRegualrDll"添加消息響應(yīng)函數(shù),圖3-3-5添加消息響應(yīng)函數(shù)并添加以下代碼:voidCDllDialog::OnButton1<>{ //TODO:Addyourcontrolnotificationhandlercodehere MessageBox<"MFCRegularDLL">;}在RegularDll.cpp的最后,添加MFC規(guī)則DLL接口函數(shù)。extern"C"__declspec<dllexport>voidShowDlg<void>{ AFX_MANAGE_STATE<AfxGetStaticModuleState<>> ; CDllDialogdllDialog; dllDialog.DoModal<>;}圖3-3-6添加MFC規(guī)則DLL接口函數(shù)在RegularDll.cpp的前面,添加#include"DllDialog.h"圖3-3-7添加MFC規(guī)則DLL接口函數(shù)完成上述步驟后,就可以編譯并生成Dll文件了。圖3-3-8添加MFC規(guī)則DLL接口函數(shù)3.4.MFC規(guī)則DLL的調(diào)用〔1首先,創(chuàng)建一個(gè)基于MFC的單文檔應(yīng)用程序"CallRegDll"。圖3-4-1創(chuàng)建MFC的單文檔應(yīng)用程序CallRegDll〔2添加一個(gè)菜單項(xiàng)"CallRegDll"。圖3-4-2添加一個(gè)菜單項(xiàng)〔3在視類對(duì)該菜單項(xiàng)添加消息響應(yīng)函數(shù),函數(shù)代碼如下:voidCCallRegDllView::OnRegdll<>{ //TODO:Addyourcommandhandlercodehere typedefvoid<*lpFun><void>; HINSTANCEhDll=NULL;//DLL句柄 hDll=LoadLibrary<"RegularDll.dll">;if<hDll!=NULL> {lpFunpShowDlg=<lpFun>GetProcAddress<hDll,"ShowDlg">;if<pShowDlg!=NULL>{ pShowDlg<>;}else{MessageBox<"DLL中函數(shù)尋找失敗">;}} else { MessageBox<"沒有找到相應(yīng)的dll">; }}〔4編譯并運(yùn)行程序。點(diǎn)擊菜單項(xiàng),會(huì)彈出如下界面:圖3-4-3運(yùn)行結(jié)果〔5將RegularDll.dll和復(fù)制到RegularDll.lib復(fù)制到CallRegDll工程的debug目錄下。圖3-4-4復(fù)制RegularDll.lib和RegularDll.dll再次編譯,運(yùn)行程序,結(jié)果如下:圖3-4-5運(yùn)行結(jié)果3.5.隱式調(diào)用上述例子中給出的是顯式調(diào)用的方式,我們也可以在EXE程序中隱式調(diào)用MFC規(guī)則DLL。將DLL工程生成的.lib文件和.dll文件拷入當(dāng)前工程所在的目錄。圖3-4-6添加.lib文件和.dll文件并在CCallRegDllView.cpp文件的頂部添加以下代碼:#pragmacomment<lib,"RegularDll.lib">//extern"C"__declspec<dllimport>voidShowDlg<void>;//把消息響應(yīng)函數(shù)CCallRegDllView::OnRegDll<>修改為以下:voidCCallRegDllView::OnRegDll<>{ //TODO:Addyourcommandhandlercodehere ShowDlg<>;}編譯運(yùn)行程序,同樣能得到正確的結(jié)果。圖3-4-7運(yùn)行結(jié)果四、MFC擴(kuò)展動(dòng)態(tài)鏈接庫的創(chuàng)建4.1.概述MFC擴(kuò)展DLL與MFC規(guī)則DLL的相同點(diǎn)在于在兩種DLL的內(nèi)部都可以使用MFC類庫,其不同點(diǎn)在于MFC擴(kuò)展DLL與應(yīng)用程序的接口可以是MFC的。MFC擴(kuò)展DLL的含義在于它是MFC的擴(kuò)展,其主要功能是實(shí)現(xiàn)從現(xiàn)有MFC庫類中派生出可重用的類。MFC擴(kuò)展DLL使用MFC動(dòng)態(tài)鏈接庫版本,因此只有用共享MFC版本生成的MFC可執(zhí)行文件〔應(yīng)用程序或規(guī)則DLL才能使用MFC擴(kuò)展DLL。MFC規(guī)則DLL被MFC向?qū)ё詣?dòng)添加了一個(gè)CWinApp的對(duì)象,而MFC擴(kuò)展DLL則不包含該對(duì)象,它只是被自動(dòng)添加了DllMain函數(shù)。對(duì)于MFC擴(kuò)展DLL,開發(fā)人員必須在DLL的DllMain函數(shù)中添加初始化和結(jié)束代碼。
總結(jié)三種DLL對(duì)DllMain入口函數(shù)的不同處理方式,可得出下表:
DLL類型入口函數(shù)非MFCDLL編程者提供DllMain函數(shù)MFC規(guī)則DLLCWinApp對(duì)象的InitInstance和ExitInstanceMFC擴(kuò)展DLLMFCDLL向?qū)蒁llMain函數(shù)對(duì)于MFC擴(kuò)展DLL,系統(tǒng)會(huì)自動(dòng)在工程中添加如下表所示的宏,這些宏為DLL和應(yīng)用程序的編寫提供了方便。像AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA這樣的宏,在DLL和應(yīng)用程序中將具有不同的定義,這取決于_AFXEXT宏是否被定義。這使得在DLL和應(yīng)用程序中,使用統(tǒng)一的一個(gè)宏就可以表示出輸出和輸入的不同意思。宏定義AFX_CLASS_IMPORT__declspec<dllexport>AFX_API_IMPORT__declspec<dllexport>AFX_DATA_IMPORT__declspec<dllexport>AFX_CLASS_EXPORT__declspec<dllexport>AFX_API_EXPORT__declspec<dllexport>AFX_DATA_EXPORT__declspec<dllexport>AFX_EXT_CLASS#ifdef_AFXEXT
AFX_CLASS_EXPORT
#else
AFX_CLASS_IMPORTAFX_EXT_API#ifdef_AFXEXT
AFX_API_EXPORT
#else
AFX_API_IMPORTAFX_EXT_DATA#ifdef_AFXEXT
AFX_DATA_EXPORT
#else
AFX_DATA_IMPORT4.2.MFC擴(kuò)展DLL導(dǎo)出MFC派生類在下述例子中,我們將新建一個(gè)名為"ExtDll"的MFC擴(kuò)展DLL工程,在這個(gè)DLL中導(dǎo)出一個(gè)對(duì)話框類,這個(gè)對(duì)話框類派生自MFC類CDialog。圖4-2-1創(chuàng)建MFC擴(kuò)展DLL圖4-2-2創(chuàng)建MFC擴(kuò)展DLL使用MFC向?qū)蒑FC擴(kuò)展DLL時(shí),系統(tǒng)會(huì)自動(dòng)添加如下代碼:staticAFX_EXTENSION_MODULEExtDllDLL={NULL,NULL};
extern"C"intAPIENTRY
DllMain<HINSTANCEhInstance,DWORDdwReason,LPVOIDlpReserved>
{
//RemovethisifyouuselpReserved
UNREFERENCED_PARAMETER<lpReserved>;
//說明:lpReserved是一個(gè)被系統(tǒng)所保留的參數(shù),對(duì)于隱式鏈接是一個(gè)非零值,對(duì)于顯式鏈接值是零
if<dwReason==DLL_PROCESS_ATTACH>
{
TRACE0<"EXTDLL.DLLInitializing!\n">;
//ExtensionDLLone-timeinitialization
if<!AfxInitExtensionModule<ExtDllDLL,hInstance>>
return0;
//InsertthisDLLintotheresourcechain
newCDynLinkLibrary<ExtDllDLL>;
}
elseif<dwReason==DLL_PROCESS_DETACH>
{
TRACE0<"EXTDLL.DLLTerminating!\n">;
//Terminatethelibrarybeforedestructorsarecalled
AfxTermExtensionModule<ExtDllDLL>;
}
return1;//ok
}代碼分析如下:
〔1上述代碼完成MFC擴(kuò)展DLL的初始化和終止處理;
〔2初始化期間所創(chuàng)建的CDynLinkLibrary對(duì)象使MFC擴(kuò)展DLL可以將DLL中的CRuntimeClass對(duì)象或資源導(dǎo)出到應(yīng)用程序;
〔3AfxInitExtensionModule函數(shù)捕獲模塊的CRuntimeClass結(jié)構(gòu)和在創(chuàng)建CDynLinkLibrary對(duì)象時(shí)使用的對(duì)象工廠〔COleObjectFactory對(duì)象;
〔4AfxTermExtensionModule函數(shù)使MFC得以在每個(gè)進(jìn)程與擴(kuò)展DLL分離時(shí)〔進(jìn)程退出或使用AfxFreeLibrary卸載DLL時(shí)清除擴(kuò)展DLL;
〔5第一條語句staticAFX_EXTENSION_MODULEExtDllDLL={NULL,NULL};定義了一個(gè)AFX_EXTENSION_MODULE類的靜態(tài)全局對(duì)象,AFX_EXTENSION_MODULE的定義如下:structAFX_EXTENSION_MODULE
{
BOOLbInitialized;
HMODULEhModule;
HMODULEhResource;
CRuntimeClass*pFirstSharedClass;
COleObjectFactory*pFirstSharedFactory;
};在資源編輯器中添加一個(gè)如下圖所示的對(duì)話框,并使用MFC類向?qū)槠涮砑右粋€(gè)對(duì)應(yīng)的類CExtDialog,系統(tǒng)自動(dòng)添加了ExtDialog.h和ExtDialog.cpp兩個(gè)頭文件。圖4-2-3添加對(duì)話框圖4-2-3添加對(duì)話框類修改ExtDialog.h中CExtDialog類的聲明為:classAFX_EXT_CLASSCExtDialog:publicCDialog
{
public:
CExtDialog<CWnd*pParent=NULL>;
enum{IDD=IDD_DLL_DIALOG};
protected:
virtualvoidDoDataExchange<CDataExchange*pDX>;
DECLARE_MESSAGE_MAP<>
};這其中最主要的改變是我們?cè)赾lassAFX_EXT_CLASSCExtDialog語句中添加了"AFX_EXT_CLASS"宏,則使得DLL中的CExtDialog類被導(dǎo)出。為對(duì)話框按鈕"MFCExtentionDLL"添加消息響應(yīng)函數(shù)voidCExtDialog::OnButton1<>{ //TODO:Addyourcontrolnotificationhandlercodehere MessageBox<"MFCExtentionDLL">;}最后,編譯運(yùn)行,生成.lib文件和.dll文件。4.3.MFC擴(kuò)展DLL的加載在上述工程所在的工作區(qū)中添加一個(gè)LoadExtDllDlg工程,用于演示MFC擴(kuò)展DLL的加載。在LoadExtDllDlg工程中添加一個(gè)如下圖所示的對(duì)話框,這個(gè)對(duì)話框上包括一個(gè)"調(diào)用DLL"按鈕。圖4-3-1MFC擴(kuò)展DLL調(diào)用工程中的對(duì)話框在與上圖對(duì)應(yīng)對(duì)話框類實(shí)現(xiàn)文件的頭部添加://LoadExtDllDlg.cpp:implementationfile
//
#include"..\ExtDialog.h"
#pragmacomment<lib,"..\Debug\ExtDll.lib">而"調(diào)用DLL"按鈕的單擊事件的消息處理函數(shù)為:voidCLoadExtDllDlg::OnDllcallButton<>
{
CExtDialogextDialog;
extDialog.DoModal<>;
}最后編譯并運(yùn)行,運(yùn)行結(jié)果如下:圖4-3-2運(yùn)行結(jié)果從上述加載過程,我們可總結(jié)出:
為提供給用戶隱式加載,MFC擴(kuò)展DLL需要提供三個(gè)文件:
〔1描述DLL中擴(kuò)展類的頭文件;
〔2與動(dòng)態(tài)鏈接庫對(duì)應(yīng)的.LIB文件;
〔3動(dòng)態(tài)鏈接庫.DLL文件本身。
有了這三個(gè)文件,應(yīng)用程序的開發(fā)者才可充分利用MFC擴(kuò)展DLL。五、動(dòng)態(tài)鏈接庫的典型應(yīng)用動(dòng)態(tài)鏈接庫DLL實(shí)現(xiàn)了庫的共享,體現(xiàn)了代碼重用的思想。我們可以把廣泛的、具有共性的、能夠多次被利用的函數(shù)和類定義在庫中。這樣,在再次使用這些函數(shù)和類的時(shí)候,就不再需要重新添加與這些函數(shù)和類相關(guān)的代碼。因此,動(dòng)態(tài)鏈接庫的應(yīng)用廣泛,而其主要的典型應(yīng)用有以下幾方面:5.1.通用的算法圖像處理、視頻音頻解碼、壓縮與解壓縮、加密與解密通常采用某些特定的算法,這些算法較固定且在這類程序中往往經(jīng)常被使用。如以下的例子:學(xué)習(xí)過較高級(jí)別數(shù)學(xué)〔概率統(tǒng)計(jì)與隨機(jī)過程、信號(hào)與線性系統(tǒng)及數(shù)字信號(hào)處理的讀者應(yīng)該知道,傅立葉變換是一種在信號(hào)分析中常用的算法,用于時(shí)域和頻域的相互轉(zhuǎn)換。FFT變換算法通用而有共性,我們適宜把它集成在一個(gè)DLL中。我們可在相關(guān)資料上獲取到FFT變換算法的函數(shù)代碼如下:/*函數(shù)名稱:FFT<>
*參數(shù):
*complex<double>*TD-指向時(shí)域數(shù)組的指針
*complex<double>*FD-指向頻域數(shù)組的指針
*r-2的冪數(shù),即迭代次數(shù)
*返回值:無。
*說明:該函數(shù)用來實(shí)現(xiàn)快速傅立葉變換
*/
voidFFT<complex<double>*TD,complex<double>*FD,intr>
{
LONGcount;//傅立葉變換點(diǎn)數(shù)
inti,j,k;//循環(huán)變量
intbfsize,p;//中間變量
doubleangle;//角度
complex<double>*W,*X1,*X2,*X;
count=1<<r;//傅立葉變換點(diǎn)數(shù)
//分配運(yùn)算所需存儲(chǔ)器
W=newcomplex<double>[count/2];
X1=newcomplex<double>[count];
X2=newcomplex<double>[count];
//計(jì)算加權(quán)系數(shù)
for<i=0;i<count/2;i++>
{
angle=-i*PI*2/count;
W[i]=complex<double><cos<angle>,sin<angle>>;
}
//將時(shí)域點(diǎn)寫入X1
memcpy<X1,TD,sizeof<complex<double>>*count>;
//采用蝶形算法進(jìn)行快速傅立葉變換
for<k=0;k<r;k++>
{
for<j=0;j<1<<k;j++>
{
bfsize=1<<<r-k>;
for<i=0;i<bfsize/2;i++>
{
p=j*bfsize;
X2[i+p]=X1[i+p]+X1[i+p+bfsize/2];
X2[i+p+bfsize/2]=<X1[i+p]-X1[i+p+bfsize/2]>*W[i*<1<<k>];
}
}
X=X1;
X1=X2;
X2=X;
}
//重新排序
for<j=0;j<count;j++>
{
p=0;
for<i=0;i<r;i++>
{
if<j&<1<<i>>
{
p+=1<<<r-i-1>;
}
}
FD[j]=X1[p];
}
//釋放內(nèi)存
deleteW;
deleteX1;
deleteX2;
}既然有了FFT這個(gè)函數(shù),我們要把它做在DLL中,作為DLL的一個(gè)接口將是十分簡(jiǎn)單的,其步驟如下:〔1利用MFC向?qū)Ы⒁粋€(gè)非MFCDLL;
〔2在工程中添加fft.h和fft.cpp兩個(gè)文件;fft.h的源代碼為:#ifndefFFT_H
#defineFFT_H
#include<complex>
usingnamespacestd;
extern"C"void__declspec<dllexport>__stdcallFFT<complex<double>*TD,complex<double>*FD,intr>;
#definePI3.1415926
#endiffft.cpp的源代碼為:/*文件名:fft.cpp*/
#include"fft.h"
void__stdcallFFT<complex<double>*TD,complex<double>*FD,intr>
{
}在任何編程語言中使用Win32APILoadLibrary都可以加載這個(gè)DLL,而使用GetProcAddress<hDll,"FFT">則可以獲得函數(shù)FFT的地址。
這個(gè)DLL中有兩點(diǎn)需要注意:
〔1使用extern"C"修飾函數(shù)聲明,否則,生成的DLL只能供C++調(diào)用;
〔2使用__stdcall修飾函數(shù)聲明及定義,__stdcall是WindowsAPI的函數(shù)調(diào)用方式。5.2.純資源DLL我們可以從DLL中獲取資源,對(duì)于一個(gè)支持多種語言的應(yīng)用程序而言,我們可以判斷操作系統(tǒng)的語言,并自動(dòng)為應(yīng)用程序加載與操作系統(tǒng)對(duì)應(yīng)的語言。這是多語言支持應(yīng)用程序的一般做法。5.3.通信控制DLL串口、網(wǎng)口的通信控制函數(shù)如果由DLL提供則可以使應(yīng)用程序輕松不少。在工業(yè)控制、modem程序甚至socket通信中,經(jīng)常使用通信控制DLL。
在Windows系統(tǒng),需通過DCB<DeviceControlBlock>對(duì)串口進(jìn)行配置。利用WindowsAPIGetCommState函數(shù)可以獲取串口當(dāng)前配置;利用SetCommState函數(shù)則可以設(shè)置串口通訊的參數(shù)。
串行通信通常按以下四步進(jìn)行:
<1>打開串口;
<2>配置串口;
<3>數(shù)據(jù)傳送;
<4>關(guān)閉串口。
由此可見,我們需要給串口控制DLL提供如下四個(gè)接口函數(shù)://打開指定的串口,其參數(shù)port為端口號(hào)
BOOLComOpen<intport>;//在這個(gè)函數(shù)里使用默認(rèn)的參數(shù)設(shè)置串口
//將打開的串口關(guān)閉
voidComClose<intport>;
//將串口接收緩沖區(qū)中的數(shù)據(jù)放到buffer中
intGetComData<char*buf,intbuf_len>;
//將指定長(zhǎng)度的數(shù)據(jù)發(fā)送到串口
intSendDataToCom<LPBYTEbuf,intbuf_Len>;下面是DLL接口的主要源代碼框架://com.h:com類通信接口
classAFX_EXT_CLASScom
{
public:
ComOpen<intport>
{
…
}
intSendDataToCom<LPBYTEbuf,
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 高考物理總復(fù)習(xí)專題二相互作用實(shí)驗(yàn)二探究彈力和彈簧伸長(zhǎng)量的關(guān)系練習(xí)含答案
- 江蘇省2015-2015學(xué)年高中英語 Unit3 Amazing people project教案 牛津譯林版必修2
- 八年級(jí)歷史下冊(cè) 第12課 欣欣向榮的科教文體事業(yè)教案 北師大版
- 2024年九年級(jí)語文上冊(cè) 第二單元 第6課《敬業(yè)與樂業(yè)》說課稿 新人教版
- 2024-2025學(xué)年高中語文 第二單元 珠星碧月彩云中 4 詞三首(一)教案 語文版必修3
- 2023四年級(jí)數(shù)學(xué)下冊(cè) 4 小數(shù)的意義和性質(zhì) 3小數(shù)點(diǎn)移動(dòng)引起小數(shù)大小的變化第2課時(shí) 小數(shù)點(diǎn)移動(dòng)引起小數(shù)大小變化的規(guī)律(2)配套教案 新人教版
- 二年級(jí)語文上冊(cè) 課文3 9 黃山奇石教案 新人教版
- 2024-2025學(xué)年新教材高中歷史 第八單元 中華民族的抗日戰(zhàn)爭(zhēng)和人民解放戰(zhàn)爭(zhēng) 第24課 全民族浴血奮戰(zhàn)與抗日戰(zhàn)爭(zhēng)的勝利教案3 新人教版必修《中外歷史綱要(上)》
- 變壓器報(bào)停委托書
- 租房電器超過使用年限合同(2篇)
- 六年級(jí)語文 六年級(jí)班家長(zhǎng)會(huì)
- 內(nèi)科學(xué)(腎臟-內(nèi)分泌-血液)知到章節(jié)答案智慧樹2023年溫州醫(yī)科大學(xué)
- 年產(chǎn)10噸功能益生菌凍干粉的工廠設(shè)計(jì)改
- 地理教育測(cè)量與評(píng)價(jià)
- 2023上海車展展前報(bào)告
- 事業(yè)單位獎(jiǎng)勵(lì)審批表主要事跡
- 中科大天文學(xué)史課件17近代天體測(cè)量和天體力學(xué)的發(fā)展
- 六年級(jí)勞動(dòng)與技術(shù)上冊(cè)教案
- 馬王堆導(dǎo)引術(shù)獨(dú)立彩圖版
- 小學(xué)一年級(jí)語文上學(xué)期教研活動(dòng)記錄(10次)
- GB/T 31315-2014機(jī)械結(jié)構(gòu)用冷拔或冷軋精密焊接鋼管
評(píng)論
0/150
提交評(píng)論