青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

ivy-jie

progress ...

C++博客 首頁 新隨筆 聯系 聚合 管理
  9 Posts :: 41 Stories :: 6 Comments :: 0 Trackbacks

一、前言

  自從微軟推出16位的Windows操作系統起,此后每種版本的Windows操作系統都非常依賴于動態鏈接庫(DLL)中的函數和數據,實際上Windows操作系統中幾乎所有的內容都由DLL以一種或另外一種形式代表著,例如顯示的字體和圖標存儲在GDI DLL中、顯示Windows桌面和處理用戶的輸入所需要的代碼被存儲在一個User DLL中、Windows編程所需要的大量的API函數也被包含在Kernel DLL中。

  在Windows操作系統中使用DLL有很多優點,最主要的一點是多個應用程序、甚至是不同語言編寫的應用程序可以共享一個DLL文件,真正實現了資源"共享",大大縮小了應用程序的執行代碼,更加有效的利用了內存;使用DLL的另一個優點是DLL文件作為一個單獨的程序模塊,封裝性、獨立性好,在軟件需要升級的時候,開發人員只需要修改相應的DLL文件就可以了,而且,當DLL中的函數改變后,只要不是參數的改變,程序代碼并不需要重新編譯。這在編程時十分有用,大大提高了軟件開發和維護的效率。

  既然DLL那么重要,所以搞清楚什么是DLL、如何在Windows操作系統中開發使用DLL是程序開發人員不得不解決的一個問題。本文針對這些問題,通過一個簡單的例子,即在一個DLL中實現比較最大、最小整數這兩個簡單函數,全面地解析了在Visual C++編譯環境下編程實現DLL的過程,文章中所用到的程序代碼在Windows98系統、Visual C++6.0編譯環境下通過。

  二、DLL的概念

  DLL是建立在客戶/服務器通信的概念上,包含若干函數、類或資源的庫文件,函數和數據被存儲在一個DLL(服務器)上并由一個或多個客戶導出而使用,這些客戶可以是應用程序或者是其它的DLL。DLL庫不同于靜態庫,在靜態庫情況下,函數和數據被編譯進一個二進制文件(通常擴展名為*.LIB),Visual C++的編譯器在處理程序代碼時將從靜態庫中恢復這些函數和數據并把他們和應用程序中的其他模塊組合在一起生成可執行文件。這個過程稱為"靜態鏈接",此時因為應用程序所需的全部內容都是從庫中復制了出來,所以靜態庫本身并不需要與可執行文件一起發行。

  在動態庫的情況下,有兩個文件,一個是引入庫(.LIB)文件,一個是DLL文件,引入庫文件包含被DLL導出的函數的名稱和位置,DLL包含實際的函數和數據,應用程序使用LIB文件鏈接到所需要使用的DLL文件,庫中的函數和數據并不復制到可執行文件中,因此在應用程序的可執行文件中,存放的不是被調用的函數代碼,而是DLL中所要調用的函數的內存地址這樣當一個或多個應用程序運行是再把程序代碼和被調用的函數代碼鏈接起來,從而節省了內存資源。從上面的說明可以看出,DLL和.LIB文件必須隨應用程序一起發行,否則應用程序將會產生錯誤。

  微軟的Visual C++支持三種DLL,它們分別是Non-MFC Dll(非MFC動態庫)、Regular Dll(常規DLL)、Extension Dll(擴展DLL)。Non-MFC DLL指的是不用MFC的類庫結構,直接用C語言寫的DLL,其導出的函數是標準的C接口,能被非MFC或MFC編寫的應用程序所調用。Regular DLL:和下述的Extension Dlls一樣,是用MFC類庫編寫的,它的一個明顯的特點是在源文件里有一個繼承CWinApp的類(注意:此類DLL雖然從CWinApp派生,但沒有消息循環),被導出的函數是C函數、C++類或者C++成員函數(注意不要把術語C++類與MFC的微軟基礎C++類相混淆),調用常規DLL的應用程序不必是MFC應用程序,只要是能調用類C函數的應用程序就可以,它們可以是在Visual C++、Dephi、Visual Basic、Borland C等編譯環境下利用DLL開發應用程序。

  常規DLL又可細分成靜態鏈接到MFC和動態鏈接到MFC上的,這兩種常規DLL的區別將在下面介紹。與常規DLL相比,使用擴展DLL用于導出增強MFC基礎類的函數或子類,用這種類型的動態鏈接庫,可以用來輸出一個從MFC所繼承下來的類。

  擴展DLL是使用MFC的動態鏈接版本所創建的,并且它只被用MFC類庫所編寫的應用程序所調用。例如你已經創建了一個從MFC的CtoolBar類的派生類用于創建一個新的工具欄,為了導出這個類,你必須把它放到一個MFC擴展的DLL中。擴展DLL 和常規DLL不一樣,它沒有一個從CWinApp繼承而來的類的對象,所以,開發人員必須在DLL中的DllMain函數添加初始化代碼和結束代碼。

三、動態鏈接庫的創建

  在Visual C++6.0開發環境下,打開File\New\Project選項,可以選擇Win32 Dynamic-Link Library或MFC AppWizard[dll]來以不同的方式來創建Non-MFC Dll、Regular Dll、Extension Dll等不同種類的動態鏈接庫。

  1. Win32 Dynamic-Link Library方式創建Non-MFC DLL動態鏈接庫

  每一個DLL必須有一個入口點,這就象我們用C編寫的應用程序一樣,必須有一個WINMAIN函數一樣。在Non-MFC DLL中DllMain是一個缺省的入口函數,你不需要編寫自己的DLL入口函數,用這個缺省的入口函數就能使動態鏈接庫被調用時得到正確的初始化。如果應用程序的DLL需要分配額外的內存或資源時,或者說需要對每個進程或線程初始化和清除操作時,需要在相應的DLL工程的.CPP文件中對DllMain()函數按照下面的格式書寫。

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:
.......
}
return TRUE;
}

  參數中,hMoudle是動態庫被調用時所傳遞來的一個指向自己的句柄(實際上,它是指向_DGROUP段的一個選擇符);ul_reason_for_call是一個說明動態庫被調原因的標志,當進程或線程裝入或卸載動態鏈接庫的時候,操作系統調用入口函數,并說明動態鏈接庫被調用的原因,它所有的可能值為:DLL_PROCESS_ATTACH: 進程被調用、DLL_THREAD_ATTACH: 線程被調用、DLL_PROCESS_DETACH: 進程被停止、DLL_THREAD_DETACH: 線程被停止;lpReserved為保留參數。到此為止,DLL的入口函數已經寫了,剩下部分的實現也不難,你可以在DLL工程中加入你所想要輸出的函數或變量了。

  我們已經知道DLL是包含若干個函數的庫文件,應用程序使用DLL中的函數之前,應該先導出這些函數,以便供給應用程序使用。要導出這些函數有兩種方法一是在定義函數時使用導出關鍵字_declspec(dllexport),另外一種方法是在創建DLL文件時使用模塊定義文件.Def。需要讀者注意的是在使用第一種方法的時候,不能使用DEF文件。下面通過兩個例子來說明如何使用這兩種方法創建DLL文件。

  1)使用導出函數關鍵字_declspec(dllexport)創建MyDll.dll,該動態鏈接庫中有兩個函數,分別用來實現得到兩個數的最大和最小數。在MyDll.h和MyDLL.cpp文件中分別輸入如下原代碼:

//MyDLL.h
extern "C" _declspec(dllexport) int Max(int a, int b);
extern "C" _declspec(dllexport) int Min(int a, int b);
//MyDll.cpp
#include<stdio.h></stdio.h>
#include"MyDll.h"
int Max(int a, int b)
{
if(a>=b)return a;
else
return b;
}
int Min(int a, int b)
{
if(a>=b)return b;
else
return a;
}

  該動態鏈接庫編譯成功后,打開MyDll工程中的debug目錄,可以看到MyDll.dll、MyDll.lib兩個文件。LIB文件中包含DLL文件名和DLL文件中的函數名等,該LIB文件只是對應該DLL文件的"映像文件",與DLL文件中,LIB文件的長度要小的多,在進行隱式鏈接DLL時要用到它。讀者可能已經注意到在MyDll.h中有關鍵字"extern C",它可以使其他編程語言訪問你編寫的DLL中的函數

  2)用.def文件創建工程MyDll

  為了用.def文件創建DLL,請先刪除上個例子創建的工程中的MyDll.h文件,保留MyDll.cpp并在該文件頭刪除#include MyDll.h語句,同時往該工程中加入一個文本文件,命名為MyDll.def,再在該文件中加入如下代碼:

LIBRARY MyDll
EXPORTS
Max
Min

  其中LIBRARY語句說明該def文件是屬于相應DLL的,EXPORTS語句下列出要導出的函數名稱。我們可以在.def文件中的導出函數后加@n,如Max@1,Min@2,表示要導出的函數順序號,在進行顯式連時可以用到它。該DLL編譯成功后,打開工程中的Debug目錄,同樣也會看到MyDll.dll和MyDll.lib文件。

  2.MFC AppWizard[dll]方式生成常規/擴展DLL

  在MFC AppWizard[dll]下生成DLL文件又有三種方式,在創建DLL是,要根據實際情況選擇創建DLL的方式。一種是常規DLL靜態鏈接到MFC,另一種是常規DLL動態鏈接到MFC。兩者的區別是:前者使用的是MFC的靜態鏈接庫,生成的DLL文件長度大,一般不使用這種方式,后者使用MFC的動態鏈接庫,生成的DLL文件長度小;動態鏈接到MFC的規則DLL所有輸出的函數應該以如下語句開始

AFX_MANAGE_STATE(AfxGetStaticModuleState( )) //此語句用來正確地切換MFC模塊狀態

  最后一種是MFC擴展DLL,這種DLL特點是用來建立MFC的派生類,Dll只被用MFC類庫所編寫的應用程序所調用。前面我們已經介紹過,Extension DLLs 和Regular DLLs不一樣,它沒有一個從CWinApp繼承而來的類的對象,編譯器默認了一個DLL入口函數DLLMain()作為對DLL的初始化,你可以在此函數中實現初始化,代碼如下:

BOOL WINAPI APIENTRY DLLMain(HINSTANCE hinstDll,DWORD reason ,LPVOID flmpload)
{
switch(reason)
{
……………//初始化代碼;
}
return true;
}

  參數hinstDll存放DLL的句柄,參數reason指明調用函數的原因,lpReserved是一個被系統所保留的參數。對于隱式鏈接是一個非零值,對于顯式鏈接值是零。

  在MFC下建立DLL文件,會自動生成def文件框架,其它與建立傳統的Non-MFC DLL沒有什么區別,只要在相應的頭文件寫入關鍵字_declspec(dllexport)函數類型和函數名等,或在生成的def文件中EXPORTS下輸入函數名就可以了。需要注意的是在向其它開發人員分發MFC擴展DLL 時,不要忘記提供描述DLL中類的頭文件以及相應的.LIB文件和DLL本身,此后開發人員就能充分利用你開發的擴展DLL了。

四、動態鏈接庫DLL的鏈接

  應用程序使用DLL可以采用兩種方式:一種是隱式鏈接,另一種是顯式鏈接。在使用DLL之前首先要知道DLL中函數的結構信息。Visual C++6.0在VC\bin目錄下提供了一個名為Dumpbin.exe的小程序,用它可以查看DLL文件中的函數結構。另外,Windows系統將遵循下面的搜索順序來定位DLL: 1.包含EXE文件的目錄,2.進程的當前工作目錄, 3.Windows系統目錄, 4.Windows目錄,5.列在Path環境變量中的一系列目錄。

  1.隱式鏈接

  隱式鏈接就是在程序開始執行時就將DLL文件加載到應用程序當中。實現隱式鏈接很容易,只要將導入函數關鍵字_declspec(dllimport)函數名等寫到應用程序相應的頭文件中就可以了。下面的例子通過隱式鏈接調用MyDll.dll庫中的Min函數。首先生成一個項目為TestDll,在DllTest.h、DllTest.cpp文件中分別輸入如下代碼:

//Dlltest.h
#pragma comment(lib,"MyDll.lib")
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
//TestDll.cpp
#include<stdio.h></stdio.h>
#include"Dlltest.h"
void main()
{int a;
a=min(8,10)
printf("比較的結果為%d\n",a);
}

  在創建DllTest.exe文件之前,要先將MyDll.dll和MyDll.lib拷貝到當前工程所在的目錄下面,也可以拷貝到windows的System目錄下。如果DLL使用的是def文件,要刪除TestDll.h文件中關鍵字extern "C"。TestDll.h文件中的關鍵字Progam commit是要Visual C+的編譯器在link時,鏈接到MyDll.lib文件,當然,開發人員也可以不使用#pragma comment(lib,"MyDll.lib")語句,而直接在工程的Setting->Link頁的Object/Moduls欄填入MyDll.lib既可。

  2.顯式鏈接

  顯式鏈接是應用程序在執行過程中隨時可以加載DLL文件,也可以隨時卸載DLL文件,這是隱式鏈接所無法作到的,所以顯式鏈接具有更好的靈活性,對于解釋性語言更為合適。不過實現顯式鏈接要麻煩一些。在應用程序中用LoadLibrary或MFC提供的AfxLoadLibrary顯式的將自己所做的動態鏈接庫調進來,動態鏈接庫的文件名即是上述兩個函數的參數,此后再用GetProcAddress()獲取想要引入的函數。自此,你就可以象使用如同在應用程序自定義的函數一樣來調用此引入函數了。在應用程序退出之前,應該用FreeLibrary或MFC提供的AfxFreeLibrary釋放動態鏈接庫。下面是通過顯式鏈接調用DLL中的Max函數的例子。

#include <studio.h></studio.h>
#include<widows.h></widows.h>
void main(void)
{
typedef int(*pMax)(int a,int b);
typedef int(*pMin)(int a,int b);
HINSTANCE hDLL;
PMax Max
HDLL=LoadLibrary("MyDll.dll");//加載動態鏈接庫MyDll.dll文件;
Max=(pMax)GetProcAddress(hDLL,"Max");
A=Max(5,8);
Printf("比較的結果為%d\n",a);
FreeLibrary(hDLL);//卸載MyDll.dll文件;
}

  在上例中使用類型定義關鍵字typedef,定義指向和DLL中相同的函數原型指針,然后通過LoadLibray()將DLL加載到當前的應用程序中并返回當前DLL文件的句柄,然后通過GetProcAddress()函數獲取導入到應用程序中的函數指針,函數調用完畢后,使用FreeLibrary()卸載DLL文件。在編譯程序之前,首先要將DLL文件拷貝到工程所在的目錄或Windows系統目錄下。

  使用顯式鏈接應用程序編譯時不需要使用相應的Lib文件。另外,使用GetProcAddress()函數時,可以利用MAKEINTRESOURCE()函數直接使用DLL中函數出現的順序號,如將GetProcAddress(hDLL,"Min")改為GetProcAddress(hDLL, MAKEINTRESOURCE(2))(函數Min()在DLL中的順序號是2),這樣調用DLL中的函數速度很快,但是要記住函數的使用序號,否則會發生錯誤。

  本文通過通俗易懂的方式,全面介紹了動態鏈接庫的概念、動態鏈接庫的創建和動態鏈接庫的鏈接,并給出個簡單明了的例子,相信讀者看了本文后,能夠創建自己的動態鏈接庫并應用到后續的軟件開發當中去了,當然,讀者要熟練操作DLL,還需要在大量的實踐中不斷摸索,希望本文能起到拋磚引玉的作用。

posted on 2009-06-22 20:46 ivy-jie 閱讀(187) 評論(0)  編輯 收藏 引用 所屬分類: MFC
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美在线视频在线播放完整版免费观看 | 久久亚洲私人国产精品va| 亚洲专区欧美专区| 一本色道久久综合亚洲二区三区| 欧美一级久久| 免费看的黄色欧美网站| 国产一区二区欧美| 欧美mv日韩mv亚洲| 欧美精品国产一区二区| 欧美一级一区| 久久在线视频在线| 久久中文字幕导航| 欧美激情第9页| 欧美大片18| 亚洲国产高清自拍| 亚洲免费观看| 一区二区三区免费网站| 性欧美超级视频| 久久成人综合视频| 男人的天堂亚洲| 亚洲免费高清| 欧美中文字幕久久| 欧美猛交免费看| 国产乱码精品1区2区3区| 尤物yw午夜国产精品视频| 一区二区不卡在线视频 午夜欧美不卡在 | 亚洲国产高清视频| 一区二区三区 在线观看视| 欧美亚洲一区在线| 亚洲精品日韩在线观看| 欧美国产日韩一二三区| 亚洲天堂成人| 久久综合精品国产一区二区三区| 欧美女主播在线| 黑人巨大精品欧美一区二区小视频| 亚洲日本精品国产第一区| 久久精品男女| 亚洲性线免费观看视频成熟| 欧美岛国激情| 亚洲国产福利在线| 久久精品国产久精国产一老狼| 欧美黄色aa电影| 久久九九免费| 国产一区二区av| 午夜精品久久久久久久99樱桃 | 夜色激情一区二区| 麻豆精品在线视频| 激情亚洲网站| 久久免费高清| 亚洲免费影视| 欧美日韩系列| 99视频一区| 91久久精品www人人做人人爽| 欧美在线三区| 韩国成人精品a∨在线观看| 午夜精品久久久久久| 亚洲精品一区久久久久久| 免费成人网www| 在线看片成人| 猛干欧美女孩| 久久精品一区四区| 尤物精品在线| 欧美国产先锋| 美日韩精品视频| 亚洲日本电影在线| 亚洲国产另类久久精品| 欧美国产欧美亚洲国产日韩mv天天看完整 | 久久精品国产第一区二区三区最新章节| 亚洲美女av电影| 欧美激情一区二区三区在线视频观看| 136国产福利精品导航网址| 美日韩免费视频| 狂野欧美激情性xxxx欧美| 91久久夜色精品国产网站| 女人香蕉久久**毛片精品| 欧美高清在线一区二区| 亚洲午夜精品久久| 亚洲欧美在线视频观看| 国产一区视频在线观看免费| 美女脱光内衣内裤视频久久网站| 欧美va亚洲va日韩∨a综合色| 一本色道久久综合亚洲精品按摩| 一本大道久久精品懂色aⅴ| 国产精品丝袜91| 老司机成人网| 欧美日韩精品是欧美日韩精品| 亚洲欧美视频在线观看视频| 性欧美激情精品| 亚洲国产欧美不卡在线观看| 亚洲三级免费电影| 国产麻豆精品视频| 欧美韩日亚洲| 国产精品久久久久久久午夜| 麻豆精品一区二区综合av| 欧美国产精品一区| 欧美一区二区三区免费观看视频| 久久久久久久网站| 宅男66日本亚洲欧美视频| 久久精品国产69国产精品亚洲| 91久久精品国产91久久性色tv | 欲色影视综合吧| 亚洲人成人一区二区三区| 国产精品自在线| 亚洲第一在线视频| 国产一区二区精品丝袜| 日韩香蕉视频| 亚洲大胆女人| 91久久精品国产| 亚洲午夜精品国产| 91久久久国产精品| 亚洲欧美成人| 一区二区久久久久久| 欧美在线免费一级片| 亚洲深夜av| 免费在线一区二区| 久久裸体艺术| 国产欧美大片| 一区二区三区高清在线| 亚洲精品免费一区二区三区| 久久久精品2019中文字幕神马| 亚洲欧美在线高清| 欧美日韩精品免费在线观看视频| 欧美国产日韩亚洲一区| 怡红院av一区二区三区| 久久久视频精品| 亚洲理论电影网| 一区二区三区在线视频免费观看 | 欧美在线亚洲在线| 亚洲视频精品在线| 欧美成人一区二区三区| 久久米奇亚洲| 狠狠色狠狠色综合日日小说| 亚洲在线观看免费视频| 亚洲欧美在线x视频| 欧美日韩一卡| 国产一区激情| 亚洲视频在线观看视频| 亚洲性色视频| 欧美性视频网站| 一区二区欧美激情| 一区二区三区 在线观看视频 | 老司机一区二区三区| 久久偷看各类wc女厕嘘嘘偷窃| 国产日韩欧美日韩| 亚洲欧美日韩国产综合| 久久国产主播| 永久免费毛片在线播放不卡| 久久久久久久网| 亚洲国产精品一区| 日韩视频欧美视频| 欧美伦理一区二区| 99国产精品视频免费观看一公开| 一区二区国产在线观看| 国产精品久久精品日日| 亚洲欧美日韩精品一区二区| 久久精品综合| 亚洲国产精品久久91精品| 欧美sm视频| 亚洲午夜三级在线| 久久裸体视频| 亚洲欧洲日本一区二区三区| 欧美日韩一区精品| 久久av红桃一区二区小说| 欧美肥婆bbw| 亚洲午夜女主播在线直播| 国产欧美日韩| 欧美 日韩 国产在线| 一区二区高清在线| 裸体一区二区三区| 亚洲激情自拍| 国产精品女人久久久久久| 久久久久久久网| 一本久道久久综合狠狠爱| 久久久久国内| 一本一本a久久| 国产私拍一区| 欧美日韩极品在线观看一区| 亚洲无玛一区| 激情亚洲网站| 欧美日韩国产成人精品| 久久国产色av| 99在线热播精品免费99热| 久久五月天婷婷| 亚洲自拍偷拍视频| 亚洲第一视频网站| 国产精品中文字幕在线观看| 欧美成人首页| 久久精品一区二区国产| 亚洲影视综合| 99人久久精品视频最新地址| 免费亚洲一区| 久久精品99国产精品| 亚洲资源av| 久久久激情视频| 一本久久青青| 在线成人h网| 国产一区二区三区网站 | 狠狠色噜噜狠狠狠狠色吗综合| 欧美人牲a欧美精品| 久久男人av资源网站|