亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? lc_bcb_105.txt

?? c++ builder 的一些txt文檔
?? TXT
?? 第 1 頁 / 共 3 頁
字號:

Windows的動態鏈接庫原理
 
  
   發信人: lov (bill), 信區: Visual
標  題: Windows的動態鏈接庫原理 一
發信站: 西北網絡中心兵馬俑 BBS 站 (Tue Dec  8 20:11:50 1998)
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-} 。 
 
10.2.1.6 編寫一般DLLs的應用舉例 
 
  在下面的程序中我們把一個字符串操作的函數儲存到一個DLLs中,以便需要的時候調用它。應該注意的一點是:為了保證這個函數可以被其它語言編寫的程序所調用,作為參數傳遞的字符串應該是無結束符的字符數組類型(即PChar類型),而不是Object  
Pascal的帶結束符的Srting類型。程序清單如下: 
 
        library Example; 
        uses 
          SysUtils, 
          Classes; 
         
    {返回字符在字符串中的位置} 
        function InStr(SourceStr: PChar;Ch: Char): Integer; export; 
        var 
          Len,i: Integer; 
        begin 
      Len := strlen(SourceStr); 
          for i := 0 to Len-1 do 
            if SourceStr[i] = ch then 
            begin 
              Result := i; 
              Exit; 
            end; 
          Result := -1; 
        end; 
         
        exports 
          Instr Index 1 name 'MyInStr' resident; 
         
        begin 
        end. 
  
 
10.2.2 調用DLLs 
 
  有兩種方法可用于調用一個儲存在DLLs中的過程。 
  1.靜態調用或顯示裝載 
  使用一個外部聲明子句,使DLLs在應用程序開始執行前即被裝入。例如: 
 
  function Instr(SourceStr : PChar;Check : Char); Integer; far; external 'UseStr'; 
 
  使用這種方法,程序無法在運行時間里決定DLLs的調用。假如一個特定的DLLs在運行時無法使用,則應用程序將無法執行。 
  2.動態調用或隱式裝載 
  使用Windows API函數LoadLibray和GetProcAddress可以實現在運行時間里動態裝載DLLs并調用其中的過程。 
  若程序只在其中的一部分調用DLLs的過程,或者程序使用哪個DLLs, 調用其中的哪個過程需要根據程序運行的實際狀態來判斷,那么使用動態調用就是一個很好的選擇。 
  使用動態調用,即使裝載一個DLLs失敗了,程序仍能繼續運行。 
 
10.2.3 靜態調用 
 
  在靜態調用一個DLLs中的過程或函數時,external指示增加到過程或函數的聲明語句中。被調用的過程或函數必須采用遠調用模式。這可以使用far過程指示或一個{$F +}編譯指示。 
  Delphi全部支持傳統Windows動態鏈接庫編程中的三種調用方式,它們是: 
  ● 通過過程/函數名 
  ● 通過過程/函數的別名 
  ● 通過過程/函數的順序號 
 
  通過過程或函數的別名調用,給用戶編程提供了靈活性,而通過順序號(Index)調用可以提高相應DLL的裝載速度。 
 
10.2.4 動態調用 
 
10.2.4.1 動態調用中的API函數 
 
  動態調用中使用的Windows API函數主要有三個,即:Loadlibrary,GetProcAddress和Freelibrary。 
   1.Loadlibrary: 把指定庫模塊裝入內存 
  語法為: 
 
  function Loadlibrary(LibFileName: PChar): THandle; 
 
    LibFileName指定了要裝載DLLs的文件名,如果LibFileName沒有包含一個路徑,則Windows按下述順序進行查找: 
  (1)當前目錄; 
  (2)Windows目錄(包含win.com的目錄)。函數GetWindowDirectory返回這一目錄的路徑; 
  (3)Windows系統目錄(包含系統文件如gdi.exe的目錄)。函數GetSystemDirectory返回這一目錄的路徑; 
  (4)包含當前任務可執行文件的目錄。利用函數GetModuleFileName可以返回這一目錄的路徑; 
  (5)列在PATH環境變量中的目錄; 
  (6)網絡的映象目錄列表。 
  如果函數執行成功,則返回裝載庫模塊的實例句柄。否則,返回一個小于HINSTANCE_ERROR的錯誤代碼。錯誤代碼的意義如下表: 
 

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
青青草成人在线观看| 色老头久久综合| 色婷婷激情综合| 精品久久久久久综合日本欧美| 中文字幕在线不卡国产视频| 久久精品国产久精国产| 欧美在线视频全部完| 国产偷国产偷亚洲高清人白洁| 午夜精彩视频在线观看不卡| 成人免费av资源| 精品精品国产高清一毛片一天堂| 亚洲一区二区免费视频| 一本一道久久a久久精品综合蜜臀| 日韩欧美成人激情| 日本在线不卡一区| 欧美日韩综合在线免费观看| 一色屋精品亚洲香蕉网站| 国产真实乱偷精品视频免| 在线播放一区二区三区| 亚洲国产一二三| 欧美亚洲另类激情小说| 亚洲视频一区二区在线| 东方欧美亚洲色图在线| 国产亚洲综合在线| 激情综合色综合久久| 精品美女一区二区| 久久国产麻豆精品| 精品少妇一区二区三区在线播放 | 捆绑调教美女网站视频一区| 欧美亚男人的天堂| 亚洲国产你懂的| 欧美日韩综合在线| 亚洲bt欧美bt精品| 91精品国产欧美一区二区| 午夜精品国产更新| 777午夜精品视频在线播放| 午夜精品久久久久久久99水蜜桃| 欧美无乱码久久久免费午夜一区| 亚洲成人精品一区| 日韩一级片网站| 精品一区二区在线播放| 久久久久国产精品免费免费搜索| 国产在线播精品第三| 精品国免费一区二区三区| 国产精品一区二区黑丝| 中文字幕永久在线不卡| 在线国产电影不卡| 三级成人在线视频| 精品国产乱码久久久久久图片| 国产乱对白刺激视频不卡 | 日韩午夜在线影院| 国产一区二区调教| 国产精品美女久久福利网站| 99re6这里只有精品视频在线观看| 一区二区不卡在线视频 午夜欧美不卡在| 在线亚洲高清视频| 美女高潮久久久| 中文字幕日本不卡| 在线不卡的av| 国产一区二区视频在线| 亚洲精品视频一区| 日韩一区二区三区在线观看| 成人黄色777网| 图片区日韩欧美亚洲| 久久久综合精品| 欧美又粗又大又爽| 极品少妇一区二区| 亚洲欧美日韩国产综合在线| 日韩一区二区影院| 不卡av在线免费观看| 日韩精品亚洲专区| 国产精品二三区| 欧美成人伊人久久综合网| 波多野结衣中文字幕一区二区三区 | 678五月天丁香亚洲综合网| 欧美网站一区二区| 国产成人精品免费网站| 午夜精品福利在线| 椎名由奈av一区二区三区| 日韩欧美中文字幕精品| 色婷婷国产精品久久包臀| 国产成人日日夜夜| 另类小说一区二区三区| 亚洲永久免费视频| 国产精品乱人伦中文| 精品久久久久一区二区国产| 欧美偷拍一区二区| 99视频热这里只有精品免费| 国产一区二区三区免费播放| 婷婷开心久久网| 亚洲一区二区三区小说| 亚洲天堂网中文字| 国产香蕉久久精品综合网| 欧美一区二区三区色| 欧美日韩精品电影| 在线日韩av片| 在线欧美小视频| 色噜噜狠狠成人网p站| 成av人片一区二区| 床上的激情91.| 国产成人小视频| 国产老女人精品毛片久久| 极品少妇xxxx精品少妇| 蜜桃av噜噜一区二区三区小说| 亚洲成人av福利| 亚洲成人一区二区| 亚洲bdsm女犯bdsm网站| 午夜视频在线观看一区| 午夜精品久久久| 日韩国产欧美三级| 日本 国产 欧美色综合| 日韩高清不卡在线| 麻豆久久久久久| 国产自产视频一区二区三区 | 亚洲福利国产精品| 亚洲第一二三四区| 视频一区二区欧美| 美女一区二区视频| 奇米一区二区三区| 久久66热偷产精品| 国产jizzjizz一区二区| 成人在线视频首页| 91蝌蚪porny| 欧美三级在线播放| 日韩一区二区在线播放| 日韩一卡二卡三卡国产欧美| 久久婷婷综合激情| 国产精品三级电影| 亚洲免费高清视频在线| 亚洲一区二区三区四区在线观看| 婷婷国产v国产偷v亚洲高清| 久久99最新地址| 成人一区在线看| 欧美亚洲动漫精品| 欧美不卡一区二区三区四区| 欧美激情一区二区三区全黄| 亚洲精品视频观看| 麻豆高清免费国产一区| 成人一区二区三区在线观看| 欧美日韩中字一区| 久久久综合网站| 亚洲综合另类小说| 韩国成人精品a∨在线观看| 成人自拍视频在线| 欧美伦理电影网| 久久久99久久| 午夜在线成人av| 国产91高潮流白浆在线麻豆 | 欧美影视一区二区三区| 日韩午夜激情av| 亚洲欧洲av色图| 久久 天天综合| 91美女片黄在线观看91美女| 欧美一级免费观看| 中文字幕在线一区二区三区| 日韩电影在线看| 99re亚洲国产精品| 精品国产三级a在线观看| 亚洲免费在线电影| 麻豆成人久久精品二区三区红 | 成人av电影免费在线播放| 欧美日韩美女一区二区| 国产精品视频yy9299一区| 日韩影院在线观看| 色综合久久久网| 亚洲精品一区二区三区四区高清| 亚洲精品视频免费看| 国产91清纯白嫩初高中在线观看 | 欧洲色大大久久| 2024国产精品| 日本成人在线电影网| 99re成人精品视频| 国产区在线观看成人精品| 麻豆精品国产91久久久久久| 欧美性受xxxx| 一区二区三区精品在线| 国产很黄免费观看久久| 日韩欧美国产一区二区在线播放| 一区二区成人在线视频| 99r国产精品| 欧美国产精品一区二区三区| 久久精品国产99| 欧美一区国产二区| 亚洲国产三级在线| 欧洲一区二区三区在线| 亚洲天堂av一区| 波多野结衣中文字幕一区 | 国产网站一区二区| 国产一区欧美一区| 日韩欧美国产一区二区在线播放| 午夜婷婷国产麻豆精品| 欧美色图在线观看| 亚洲成人资源网| 欧美精品777| 日本中文字幕一区二区有限公司| 欧美久久高跟鞋激| 日本女优在线视频一区二区| 欧美精品色一区二区三区| 亚洲成人av福利| 日韩一区二区三区在线视频|