黄色在线观看视频-黄色在线免费看-黄色在线视频免费-黄色在线视频免费看-免费啪啪网-免费啪啪网站

首頁 考試吧論壇 Exam8視線 考試商城 網絡課程 模擬考試 考友錄 實用文檔 求職招聘 論文下載
2011中考 | 2011高考 | 2012考研 | 考研培訓 | 在職研 | 自學考試 | 成人高考 | 法律碩士 | MBA考試
MPA考試 | 中科院
四六級 | 職稱英語 | 商務英語 | 公共英語 | 托福 | 雅思 | 專四專八 | 口譯筆譯 | 博思 | GRE GMAT
新概念英語 | 成人英語三級 | 申碩英語 | 攻碩英語 | 職稱日語 | 日語學習 | 法語 | 德語 | 韓語
計算機等級考試 | 軟件水平考試 | 職稱計算機 | 微軟認證 | 思科認證 | Oracle認證 | Linux認證
華為認證 | Java認證
公務員 | 報關員 | 銀行從業資格 | 證券從業資格 | 期貨從業資格 | 司法考試 | 法律顧問 | 導游資格
報檢員 | 教師資格 | 社會工作者 | 外銷員 | 國際商務師 | 跟單員 | 單證員 | 物流師 | 價格鑒證師
人力資源 | 管理咨詢師考試 | 秘書資格 | 心理咨詢師考試 | 出版專業資格 | 廣告師職業水平
駕駛員 | 網絡編輯
衛生資格 | 執業醫師 | 執業藥師 | 執業護士
會計從業資格考試會計證) | 經濟師 | 會計職稱 | 注冊會計師 | 審計師 | 注冊稅務師
注冊資產評估師 | 高級會計師 | ACCA | 統計師 | 精算師 | 理財規劃師 | 國際內審師
一級建造師 | 二級建造師 | 造價工程師 | 造價員 | 咨詢工程師 | 監理工程師 | 安全工程師
質量工程師 | 物業管理師 | 招標師 | 結構工程師 | 建筑師 | 房地產估價師 | 土地估價師 | 巖土師
設備監理師 | 房地產經紀人 | 投資項目管理師 | 土地登記代理人 | 環境影響評價師 | 環保工程師
城市規劃師 | 公路監理師 | 公路造價師 | 安全評價師 | 電氣工程師 | 注冊測繪師 | 注冊計量師
繽紛校園 | 實用文檔 | 英語學習 | 作文大全 | 求職招聘 | 論文下載 | 訪談 | 游戲
您現在的位置: 考試吧(Exam8.com) > 計算機等級考試 > 計算機二級 > Delphi > 復習資料 > 正文

2011計算機等級考試Delphi講義:動態鏈接庫編程

來源:考試吧Exam8.com) 2010-10-27 15:08:06 考試吧:中國教育培訓第一門戶 模擬考場
本章主要介紹Windows的動態鏈接庫原理、DLLs的編寫和調用、利用DLLs實現數據傳輸、利用DLLs實現窗體重用。

  第十章 動態鏈接庫編程

  10.1 Windows的動態鏈接庫原理

  動態鏈接庫(DLLs)是從C語言函數庫和Pascal庫單元的概念發展而來的。所有的C語言標準庫函數都存放在某一函數庫中,同時用戶也可以用LIB程序創建自己的函數庫。在鏈接應用程序的過程中,鏈接器從庫文件中拷貝程序調用的函數代碼,并把這些函數代碼添加到可執行文件中。這種方法同只把函數儲存在已編譯的.OBJ文件中相比更有利于代碼的重用。

  但隨著Windows這樣的多任務環境的出現,函數庫的方法顯得過于累贅。如果為了完成屏幕輸出、消息處理、內存管理、對話框等操作,每個程序都不得不擁有自己的函數,那么Windows程序將變得非常龐大。Windows的發展要求允許同時運行的幾個程序共享一組函數的單一拷貝。動態鏈接庫就是在這種情況下出現的。動態鏈接庫不用重復編譯或鏈接,一旦裝入內存,Dlls函數可以被系統中的任何正在運行的應用程序軟件所使用,而不必再將DLLs函數的另一拷貝裝入內存。

  10.1.1 動態鏈接庫的工作原理

  “動態鏈接”這幾字指明了DLLs是如何工作的。對于常規的函數庫,鏈接器從中拷貝它需要的所有庫函數,并把確切的函數地址傳送給調用這些函數的程序。而對于DLLs,函數儲存在一個獨立的動態鏈接庫文件中。在創建Windows程序時,鏈接過程并不把DLLs文件鏈接到程序上。直到程序運行并調用一個DLLs中的函數時,該程序才要求這個函數的地址。此時Windows才在DLLs中尋找被調用函數,并把它的地址傳送給調用程序。采用這種方法,DLLs達到了復用代碼的極限。

  動態鏈接庫的另一個方便之處是對動態鏈接庫中函數的修改可以自動傳播到所有調用它的程序中,而不必對程序作任何改動或處理。

  DLLs不僅提供了函數重用的機制,而且提供了數據共享的機制。任何應用程序都可以共享由裝入內存的DLLs管理的內存資源塊。只包含共享數據的DLLs稱為資源文件。如Windows的字體文件等。

  10.1.2 Windows系統的動態鏈接庫

  Windows本身就是由大量的動態鏈接庫支持的。這包括Windows API函數 ( KRNLx86.EXE,USER.EXE,GDI.EXE,…),各種驅動程序文件,各種帶有.Fon和.Fot 擴展名的字體資源文件等。Windows還提供了針對某一功能的專用DLLs,如進行DDE編程的ddeml.dll,進行程序安裝的ver.dll等。

  雖然在編寫Windows程序時必然要涉及到DLLs,但利用Delphi ,用戶在大部分時候并不會注意到這一點。這一方面是因為Delphi提供了豐富的函數使用戶不必直接去使用Windows API;另一方面即使使用Windows API,由于Delphi把API函數和其它Windows DLLs函數重新組織到了幾個庫單元中,因而也不必使用特殊的調用格式。所以本章的重點放在編寫和調用用戶自定義的DLLs上。

  使用傳統的Windows編程方法來創建和使用一個DLLs是一件很令人頭痛的事,正如傳統的Windows編程方法本身就令人生畏一樣。用戶需要對定義文件、工程文件進行一系列的修改以適應創建和使用DLLs的需要。Delphi的出現,在這一方面,正如在其它許多方面所做的那樣,減輕了開發者的負擔。更令人興奮的是Delphi利用DLLs 實現了窗體的重用機制。用戶可以將自己設計好的窗體儲存在一個DLLs中,在需要的時候可隨時調用它。

  10.2 DLLs的編寫和調用

  10.2.1 DLLs的編寫

  在Delphi環境中,編寫一個DLLs同編寫一個一般的應用程序并沒有太大的區別。事實上作為DLLs 主體的DLL函數的編寫,除了在內存、資源的管理上有所不同外,并不需要其它特別的手段。真正的區別在工程文件上。

  在絕大多數情況下,用戶幾乎意識不到工程文件的存在,因為它一般不顯示在屏幕上。如果想查看工程文件,則可以打開View菜單選擇Project Source項,此時工程文件的代碼就會出現在屏幕的Code Editor(代碼編輯器)中。

  一般工程文件的格式為:

  program 工程標題;

  uses 子句;

  程序體

  而DLLs工程文件的格式為:

  library 工程標題;

  uses 子句;

  exprots 子句;

  程序體

  它們主要的區別有兩點:

  1.一般工程文件的頭標用program關鍵字,而DLLs工程文件頭標用library 關鍵字。不同的關鍵字通知編譯器生成不同的可執行文件。用program關鍵字生成的是.exe文件,而用library關鍵字生成的是.dll文件;

  2.假如DLLs要輸出供其它應用程序使用的函數或過程,則必須將這些函數或過程列在exports子句中。而這些函數或過程本身必須用export編譯指令進行編譯。

  根據DLLs完成的功能,我們把DLLs分為如下的三類:

  1.完成一般功能的DLLs;

  2.用于數據交換的DLLs;

  3.用于窗體重用的DLLs。

  這一節我們只討論完成一般功能的DLLs,其它內容將在后邊的兩節中討論。

  10.2.1.1 編寫一般DLLs的步驟

  編寫一般DLLs的步驟如下:

  1.利用Delphi的應用程序模板,建立一個DLLs程序框架。

  對于Delphi 1.0的用戶,由于沒有DLLs模板,因此:

  (1).建立一個一般的應用程序,并打開工程文件;

  (2).移去窗體和相應的代碼單元;

  (3).在工程文件中,把program改成library,移去Uses子句中的Forms,并添加適當的庫單元(一般SysUtils、Classes是需要的),刪去begin...end之間的所有代碼。

  2.以適當的文件名保持文件,此時library后跟的庫名自動修改;

  3.輸入過程、函數代碼。如果過程、函數準備供其它應用程序調用,則在過程、函數頭后加上export 編譯指示;

  4.建立exports子句,包含供其它應用程序調用的函數和過程名。可以利用標準指示 name 、Index、resident以方便和加速過程/函數的調用;

  5.輸入庫初始化代碼。這一步是可選的;

  6.編譯程序,生成動態鏈接庫文件。

  10.2.1.2 動態鏈接庫中的標準指示

  在動態鏈接庫的輸出部分,用到了三個標準指示:name、Index、resident。

  1.name

  name后面接一個字符串常量,作為該過程或函數的輸出名。如:

  exports

  InStr name MyInstr;

  其它應用程序將用新名字(MyInstr)調用該過程或函數。如果仍利用原來的名字(InStr),則在程序執行到引用點時會引發一個系統錯誤。

  2.Index

  Index指示為過程或函數分配一個順序號。如果不使用Index指示,則由編譯器按順序進行分配。

  Index后所接數字的范圍為1...32767。使用Index可以加速調用過程。

  3.resident

  使用resident,則當DLLs裝入時特定的輸出信息始終保持在內存中。這樣當其它應用程序調用該過程時,可以比利用名字掃描DLL入口降低時間開銷。

  對于那些其它應用程序常常要調用的過程或函數,使用resident指示是合適的。例如:

  exports

  InStr name MyInStr resident;

  10.2.1.3 DLLs中的變量和段

  一個DLLs擁有自己的數據段(DS),因而它聲明的任何變量都為自己所私有。調用它的模塊不能直接使用它定義的變量。要使用必須通過過程或函數界面才能完成。而對DLLs來說,它永遠都沒有機會使用調用它的模塊中聲明的變量。

  一個DLLs沒有自己的堆棧段(SS),它使用調用它的應用程序的堆棧。因此在DLL中的過程、函數絕對不要假定DS = SS。一些語言在小模式編譯下有這種假設,但使用Delphi可以避免這種情況。Delphi絕不會產生假定DS = SS的代碼,Delphi的任何運行時間庫過程/函數也都不作這種假定。需注意的是如果讀者想嵌入匯編語言代碼,絕不要使SS和DS登錄同一個值。

  10.2.1.4 DLLs中的運行時間錯和處理

  由于DLLs無法控制應用程序的運行,導致很難進行異常處理,因此編寫DLLs時要十分小心,以確保被調用時能正常執行 。當DLLs中發生一個運行時間錯時,相應DLLs并不一定從內存中移去(因為此時其它應用程序可能正在用它),而調用DLLs的程序異常中止。這樣造成的問題是當DLLs已被修改,重新進行調用時,內存中保留的仍然可能是以前的版本,修改后的程序并沒有得到驗證。對于這個問題,有以下兩種解決方法:

  1.在程序的異常處理部分顯式將DLL卸出內存;

  2.完全退出Windows,而后重新啟動,運行相應的程序。

  同一般的應用程序相比,DLL中運行時間錯的處理是很困難的,而造成的后果也更為嚴重。因此要求程序設計者在編寫代碼時要有充分、周到的考慮。

  10.2.1.5 庫初始化代碼的編寫

  傳統Windows中動態鏈接庫的編寫,需要兩個標準函數:LibMain和WEP,用于啟動和關閉DLL。在LibMain中,可以執行開鎖DLL數據段、分配內存、初始化變量等初始化工作;而WEP在從內存中移去DLLs前被調用,一般用于進行必要的清理工作,如釋放內存等。Delphi用自己特有的方式實現了這兩個標準函數的功能。這就是在工程文件中的begin...end部分添加初始化代碼。和傳統Windows編程方法相比,它的主要特色是:

  1.初始化代碼是可選的。一些必要的工作(如開鎖數據段)可以由系統自動完成。所以大部分情況下用戶不會涉及到;

  2.可以設置多個退出過程,退出時按順序依次被調用;

  3.LibMain和WEP對用戶透明,由系統自動調用。

  初始化代碼完成的主要工作是:

  1.初始化變量、分配全局內存塊、登錄窗口對象等初始化工作。在(10.3.2)節“利用DLLs實現應用程序間的數據傳輸”中,用于數據共享的全局內存塊就是在初始化代碼中分配的。

  2.設置DLLs退出時的執行過程。Delphi有一個預定義變量ExitProc用于指向退出過程的地址。用戶可以把自己的過程名賦給ExitProc。系統自動調用WEP函數,把ExitProc指向的地址依次賦給WEP執行,直到ExitProc為nil。

  下邊的一段程序包含一個退出過程和一段初始化代碼,用來說明如何正確設置退出過程。

  library Test;

  {$S-}

  uses WinTypes, WinProcs;

  var

  SaveExit: Pointer;

  procedure LibExit; far;

  begin

  if ExitCode = wep_System_Exit then

  begin

  { 系統關閉時的相應處理 }

  end

  else

  begin

  { DLL卸出時的相應處理 }

  end;

  ExitProc := SaveExit; { 恢復原來的退出過程指針 }

  end;

  begin

  {DLL的初始化工作 }

  SaveExit := ExitProc; { 保存原來的退出過程指針 }

  ExitProc := @LibExit; { 安裝新的退出過程 }

  end.

  在初始化代碼中,首先把原來的退出過程指針保存到一個變量中,而后再把新的退出過程地址賦給ExitProc。而在自定義退出過程LibExit結束時再把ExitProc的值恢復。由于ExitProc是一個系統全局變量,所以在結束時恢復原來的退出過程是必要的。

  退出過程LibExit中使用了一個系統定義變量ExitCode,用于標志退出時的狀態。 ExitCode的取值與意義如下:

  表10.1 ExitCode的取值與意義

  ━━━━━━━━━━━━━━━━━━━━━

  取 值 意 義

  —————————————————————

  WEP_System_Exit Windows關閉

  WEP_Free_DLLx DLLs被卸出

  ━━━━━━━━━━━━━━━━━━━━━

  退出過程編譯時必須關閉stack_checking,因而需設置編譯指示 {$S-} 。

1 2 3 4 5 下一頁
  相關推薦:2010年9月計算機等級考試試題及答案解析專題
       預告:名師解析2010年9月計算機等級考試試題答案
       2010年9月計算機等級考試成績查詢時間及入口
       2010年9月計算機等考成績查詢短信免費提醒開通
文章搜索
版權聲明:如果計算機等級考試網所轉載內容不慎侵犯了您的權益,請與我們聯系800@exam8.com,我們將會及時處理。如轉載本計算機等級考試網內容,請注明出處。
主站蜘蛛池模板: 午夜黄色福利 | 欧美视频在线免费 | 国产一级特黄a大片99 | 亚洲精品视频导航 | 99视频在线精品免费 | 日本精品中文字幕在线播放 | 日韩大片免费观看视频播放 | 日韩中文字幕久久精品 | 日本xxxxx在线观看 | 成人免费在线观看网站 | 九九精品视频免费 | 欧美成人精品第一区二区三区 | 日日干日日操日日射 | 插菊综合网 | 午夜国产精品视频 | 免费a级人成a大片在线观看 | 亚洲欧美在线视频观看 | 99热国产在线 | 亚洲美女操 | 天天做天天爱天天做天天吃中 | 国产日韩欧美一区二区 | 日本精品一区二区三区在线视频 | 日本不卡视频在线播放 | 日韩色影院| 亚洲码和乱人伦中文一区 | 日韩一级欧美一级在线观看 | 午夜免费 | 久久笫一福利免费导航 | 91精品一区二区三区在线 | 久操视频在线观看 | 福利片 在线 | 又长又深又硬又黄又猛又爽 | 国产精品免费视频网站 | 精品剧情v国产在线麻豆 | 亚洲免费在线观看 | 中日韩免费视频 | 日韩三级黄色片 | 免看一级一片一在线看 | 日韩欧美亚洲一区精选 | 天天插天天舔 | 东京一本热 |