亚洲欧美第一页_禁久久精品乱码_粉嫩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在线| 日本午夜一本久久久综合| 激情综合网天天干| 国产精品中文字幕一区二区三区| 国产精品1区2区3区| 成人高清在线视频| 91色在线porny| 91视频免费播放| 2023国产精品| 亚洲最快最全在线视频| 秋霞午夜鲁丝一区二区老狼| 国产在线精品免费| 在线看国产一区| 国产亚洲va综合人人澡精品| 亚洲欧洲日产国码二区| 美女性感视频久久| 成人一区二区视频| 91精品国产色综合久久不卡蜜臀| 日韩亚洲欧美一区二区三区| 18成人在线观看| 国产一区在线看| 91精品国产综合久久蜜臀 | 成年人国产精品| 日韩精品一区二区三区视频| 日韩久久一区二区| 99在线精品观看| 国产日韩精品一区二区浪潮av| 国产欧美一区二区精品婷婷| 成人免费看的视频| 国产精品女同一区二区三区| 亚洲天堂久久久久久久| 亚洲一区视频在线| 成人性生交大片| 欧美mv日韩mv| 亚洲第一激情av| 91免费视频网| 欧美激情综合五月色丁香小说| 亚洲一区二区三区四区五区黄| 国产福利一区在线| 日韩欧美国产wwwww| 成人福利视频网站| 日韩一级黄色片| 国产精品77777竹菊影视小说| 国产人成一区二区三区影院| 国产成人av电影在线观看| 久久伊99综合婷婷久久伊| 粉嫩av亚洲一区二区图片| 欧美大黄免费观看| 国产在线精品一区在线观看麻豆| 日韩一区国产二区欧美三区| 久久国产人妖系列| 国产精品拍天天在线| 在线观看日韩精品| 日本中文在线一区| 国产精品白丝在线| 91麻豆精品国产无毒不卡在线观看| 毛片av中文字幕一区二区| 国产精品色哟哟网站| 日本韩国一区二区| 久久亚洲精品小早川怜子| 成人黄色在线看| 色先锋aa成人| 欧美中文一区二区三区| 在线播放国产精品二区一二区四区| 国产91丝袜在线播放| 日韩中文字幕一区二区三区| 亚洲视频在线一区| 亚洲色图另类专区| 久久日韩粉嫩一区二区三区| 欧美日韩国产成人在线免费| 国产成人久久精品77777最新版本| 亚洲日本在线看| 国产精品视频观看| 国产三级一区二区| 日韩免费一区二区| 91同城在线观看| 床上的激情91.| 99这里都是精品| 色婷婷久久综合| 99精品1区2区| 国产精品一区在线观看你懂的| 精品在线免费观看| 精品一区二区三区影院在线午夜| 丝袜美腿一区二区三区| 三级影片在线观看欧美日韩一区二区| 亚洲人成小说网站色在线| 中文字幕制服丝袜一区二区三区| 久久久久久久综合色一本| 91精品福利在线| 91麻豆精品国产91久久久久久久久| 色8久久精品久久久久久蜜| 在线观看亚洲a| 欧美浪妇xxxx高跟鞋交| 91精品久久久久久久99蜜桃| 日韩欧美不卡在线观看视频| 国产日韩欧美综合在线| 亚洲午夜羞羞片| 国产精品影视网| 欧美一区二区在线免费播放 | 精品久久五月天| 成人欧美一区二区三区黑人麻豆 | 亚洲午夜精品网| 偷拍一区二区三区| 精品一区二区在线播放| 成人av电影观看| 欧美一区二区三区视频免费播放| 欧美精品一区二区三区在线| 中文字幕不卡在线播放| 日韩激情中文字幕| 欧美日韩电影一区| 亚洲aaa精品| 欧美日韩三级在线| 亚洲国产精品久久不卡毛片| 欧美在线高清视频| 亚洲综合在线视频| 欧美日韩一本到| 免费在线观看成人| 久久久久久久综合日本| 狠狠色综合色综合网络| 欧美草草影院在线视频| 国产真实乱对白精彩久久| 国产日韩精品久久久| 顶级嫩模精品视频在线看| 综合婷婷亚洲小说| 欧美一区二区三区播放老司机| 天天做天天摸天天爽国产一区 | 日韩精品一二区| 欧美日韩国产综合视频在线观看| 日本免费在线视频不卡一不卡二| 日韩三级视频中文字幕| 国产精品系列在线播放| 亚洲精品高清视频在线观看| 欧美片网站yy| 岛国av在线一区| 亚洲福利一区二区| 国产亲近乱来精品视频| 欧美在线视频日韩| 国产精品一区二区91| 亚洲国产精品久久久男人的天堂| 精品美女被调教视频大全网站| 成人午夜av在线| 精品中文av资源站在线观看| 亚洲国产中文字幕| 欧美韩国日本综合| 精品日韩一区二区| 欧美日韩你懂得| 色婷婷综合久久久久中文| 国产麻豆精品theporn| 天天影视涩香欲综合网| 亚洲一区中文日韩| 亚洲最大成人网4388xx| 成人欧美一区二区三区| 国产亚洲精品超碰| 26uuu另类欧美| 久久久久国色av免费看影院| 日韩欧美在线网站| 日韩一区二区精品| 日韩精品一区二区三区视频播放| 欧美一区二区三区喷汁尤物| 7777女厕盗摄久久久| 欧美日韩精品一区视频| 日韩欧美一二三四区| 欧美变态tickling挠脚心| 欧美va在线播放| 欧美韩日一区二区三区| 亚洲天堂精品视频| 天天综合色天天综合| 国产一区二区三区精品视频| 高清beeg欧美| 91国产福利在线| 日韩视频免费观看高清在线视频| 亚洲精品一区二区三区四区高清 | 极品瑜伽女神91| 狠狠网亚洲精品| 欧美综合一区二区| 欧美mv日韩mv国产网站app| 国产精品色哟哟| 五月婷婷综合激情| 国产成人h网站| 欧美精品日韩一本| 中文字幕二三区不卡| 亚洲成av人片一区二区梦乃| 精品中文字幕一区二区小辣椒| kk眼镜猥琐国模调教系列一区二区| 色综合视频在线观看| 久久五月婷婷丁香社区| 亚洲老司机在线| 国产不卡在线播放| 欧美不卡一二三|