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

C++ Programmer's Cookbook

{C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

基于Visual C++6.0的DLL編程實現

基于 Visual C++6.0 DLL 編程實現

一、前言

  自從微軟推出 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 開發環境下,打開 FileNewProject 選項,可以選擇 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
#i nclude
#i nclude"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 并在該文件頭刪除 #i nclude 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中函數的結構信息。Visual C++6.0VCin目錄下提供了一個名為Dumpbin.exe的小程序,用它可以查看DLL文件中的函數結構。另外,Windows系統將遵循下面的搜索順序來定位DLL 1.包含EXE文件的目錄,2.進程的當前工作目錄, 3Windows系統目錄, 4Windows目錄,5.列在Path環境變量中的一系列目錄。

  1.隱式鏈接

  隱式鏈接就是在程序開始執行時就將DLL文件加載到應用程序當中。實現隱式鏈接很容易,只要將導入函數關鍵字_declspec(dllimport)函數名等寫到應用程序相應的頭文件中就可以了。下面的例子通過隱式鏈接調用MyDll.dll庫中的Min函數。首先生成一個項目為TestDll,在DllTest.hDllTest.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
#i nclude
#i nclude"Dlltest.h"
void main()
{int a;
a=min(8,10)
printf("
比較的結果為 %d " 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 函數的例子。
 

#i nclude
#i nclude
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 " 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 中的函數速度很快,但是要記住函數的使用序號,否則會發生錯誤。

posted on 2006-07-24 19:18 夢在天涯 閱讀(2488) 評論(2)  編輯 收藏 引用 所屬分類: CPlusPlus

評論

# re: 基于Visual C++6.0的DLL編程實現 2007-07-09 11:25 冬冬壞家伙

大哥,我是剛如大學,學習C++的一個新手。

有個問題問下,我有個課程設計完成不了,想請大蝦們幫幫忙。

課程題目是:足球俱樂部管理系統。

求助...!!!  回復  更多評論   

# re: 基于Visual C++6.0的DLL編程實現 2010-01-16 19:58 Harry.L

“從上面的說明可以看出, DLL 和 .LIB 文件必須隨應用程序一起發行,否則應用程序將會產生錯誤。”這個說法不準確吧!除了DLL文件外,其對應的.LIB文件不必隨應用程序一起發行。  回復  更多評論   

公告

EMail:itech001#126.com

導航

統計

  • 隨筆 - 461
  • 文章 - 4
  • 評論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1812196
  • 排名 - 5

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
              国产精品久久久久婷婷| 欧美国产激情| 国产欧美精品一区二区色综合| 亚洲天堂成人在线观看| 亚洲图片欧洲图片av| 国产精品v欧美精品v日本精品动漫| 亚洲视频国产视频| 亚洲小说欧美另类社区| 国产无遮挡一区二区三区毛片日本| 性xx色xx综合久久久xx| 性做久久久久久| 伊人久久综合| 亚洲日本视频| 国产精品成av人在线视午夜片| 亚洲欧美日韩一区二区三区在线| 亚洲欧美伊人| 久久国产精品黑丝| 亚洲精选久久| 国产精品尤物| 玖玖玖国产精品| 欧美jizz19hd性欧美| 9人人澡人人爽人人精品| 99国产精品久久久久久久| 国产精品日本一区二区| 老鸭窝毛片一区二区三区| 女生裸体视频一区二区三区| 亚洲视频免费观看| 欧美制服丝袜| 一本色道精品久久一区二区三区| 亚洲欧美在线高清| 日韩视频国产视频| 久久国产88| 夜夜嗨av一区二区三区中文字幕 | 欧美午夜在线一二页| 久久成人免费日本黄色| 欧美超级免费视 在线| 亚洲欧美美女| 男女精品网站| 久久动漫亚洲| 欧美午夜视频在线| 亚洲国产精品视频| 国产亚洲欧美一区在线观看| 亚洲精品影视| 亚洲大片免费看| 亚洲综合视频1区| 日韩亚洲一区二区| 久久人人九九| 久久久av毛片精品| 国产精品乱码人人做人人爱| 亚洲高清免费在线| 国产在线视频欧美| 亚洲欧美日韩中文在线制服| 一区二区免费看| 久久免费视频这里只有精品| 欧美在线观看一区二区| 欧美日韩亚洲国产一区| 欧美大片18| 激情五月综合色婷婷一区二区| 亚洲午夜激情网站| 亚洲一区网站| 欧美午夜片在线观看| 亚洲国产一区二区精品专区| 亚洲国产导航| 蜜桃av综合| 欧美freesex8一10精品| 在线观看国产精品网站| 欧美在线一级视频| 另类亚洲自拍| 伊人成人在线视频| 久久综合网hezyo| 欧美成人精品一区| 亚洲国产精品小视频| 欧美成人按摩| 亚洲精品视频一区二区三区| 亚洲精品婷婷| 欧美日韩在线观看一区二区| 亚洲精品久久久久久久久| 亚洲深夜av| 国产精品免费aⅴ片在线观看| 亚洲一区二区在线观看视频| 亚洲永久免费av| 久久久欧美一区二区| 亚洲美女一区| 一区二区三区.www| 欧美日韩在线看| 日韩午夜三级在线| 欧美自拍偷拍| 亚洲大胆人体在线| 欧美涩涩视频| 欧美在线电影| 最新国产成人av网站网址麻豆| 亚洲精品免费在线播放| 欧美日韩国产小视频| 亚洲私人影院在线观看| 久久精品视频在线免费观看| 原创国产精品91| 欧美日本在线播放| 亚洲女ⅴideoshd黑人| 久久婷婷蜜乳一本欲蜜臀| 亚洲黄色三级| 国产精品视频999| 久久久久国产一区二区三区| 亚洲黄色有码视频| 久久国产精品久久久久久久久久| 亚洲电影下载| 国产精品高清一区二区三区| 久久精品亚洲| 一区二区三区日韩| 欧美成人四级电影| 性欧美大战久久久久久久免费观看 | 欧美在线资源| 亚洲精品女人| 国产综合网站| 欧美视频四区| 乱码第一页成人| 午夜欧美精品| 亚洲日韩欧美视频一区| 久久天天狠狠| 欧美亚洲一级| 中文无字幕一区二区三区| 在线观看成人av| 国产精品毛片在线| 欧美精品一区二区三区在线播放 | 亚洲天堂网在线观看| 亚洲三级色网| 亚洲电影av在线| 久久亚洲一区二区三区四区| 午夜影院日韩| 亚洲午夜在线观看| 亚洲另类黄色| 亚洲精品1区2区| 精品99视频| 黄色综合网站| 国产一区二区三区精品久久久| 欧美日韩精品在线| 欧美激情精品久久久久久变态 | 亚洲福利小视频| 亚洲福利精品| 亚洲国产第一页| 欧美高清视频一区二区| 狼人社综合社区| 久久精品在线| 久久久国产精彩视频美女艺术照福利| 亚洲欧美日韩在线播放| 亚洲一区二区三区乱码aⅴ| aa级大片欧美三级| 亚洲美女精品一区| 99re视频这里只有精品| aaa亚洲精品一二三区| 一级成人国产| 国产欧美一区二区三区沐欲| 亚洲女性喷水在线观看一区| 99精品热6080yy久久| 亚洲美女毛片| 日韩视频中文| 亚洲午夜视频在线观看| 一区二区三区日韩欧美| 亚洲性图久久| 欧美伊人久久久久久午夜久久久久| 亚洲欧美视频一区| 欧美在线影院| 欧美成人嫩草网站| 欧美日韩亚洲三区| 国产精品日韩欧美一区| 极品日韩久久| 亚洲精品久久久久久久久久久久久 | 欧美日韩国产麻豆| 欧美午夜欧美| 国产在线精品一区二区中文 | 欧美精品精品一区| 欧美日韩在线一区| 国产亚洲一级| 91久久国产自产拍夜夜嗨| 一二美女精品欧洲| 久久国产精品亚洲77777| 免费日韩成人| 一本久久青青| 久久久精品2019中文字幕神马| 久久天堂av综合合色| 国产精品videossex久久发布| 国产人成一区二区三区影院| 亚洲国产99精品国自产| 亚洲网站在线看| 麻豆国产精品va在线观看不卡 | 亚洲女ⅴideoshd黑人| 久久综合色婷婷| 亚洲视频免费在线| 久久久久久久欧美精品| 欧美日韩直播| 在线观看成人av| 午夜久久电影网| 欧美国产日产韩国视频| 亚洲综合电影| 欧美精品99| 伊人激情综合| 欧美一区激情| 亚洲精品日韩欧美| 久久综合一区二区| 国产丝袜一区二区| 一区二区三区视频免费在线观看|