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

2011計算機(jī)等級考試Delphi講義:動態(tài)鏈接庫編程

本章主要介紹Windows的動態(tài)鏈接庫原理、DLLs的編寫和調(diào)用、利用DLLs實(shí)現(xiàn)數(shù)據(jù)傳輸、利用DLLs實(shí)現(xiàn)窗體重用。

  10.2.1.6 編寫一般DLLs的應(yīng)用舉例

  在下面的程序中我們把一個字符串操作的函數(shù)儲存到一個DLLs中,以便需要的時候調(diào)用它。應(yīng)該注意的一點(diǎn)是:為了保證這個函數(shù)可以被其它語言編寫的程序所調(diào)用,作為參數(shù)傳遞的字符串應(yīng)該是無結(jié)束符的字符數(shù)組類型(即PChar類型),而不是Object Pascal的帶結(jié)束符的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 調(diào)用DLLs

  有兩種方法可用于調(diào)用一個儲存在DLLs中的過程。

  1.靜態(tài)調(diào)用或顯示裝載

  使用一個外部聲明子句,使DLLs在應(yīng)用程序開始執(zhí)行前即被裝入。例如:

  function Instr(SourceStr : PChar;Check : Char); Integer; far; external 'UseStr';

  使用這種方法,程序無法在運(yùn)行時間里決定DLLs的調(diào)用。假如一個特定的DLLs在運(yùn)行時無法使用,則應(yīng)用程序?qū)o法執(zhí)行。

  2.動態(tài)調(diào)用或隱式裝載

  使用Windows API函數(shù)LoadLibray和GetProcAddress可以實(shí)現(xiàn)在運(yùn)行時間里動態(tài)裝載DLLs并調(diào)用其中的過程。

  若程序只在其中的一部分調(diào)用DLLs的過程,或者程序使用哪個DLLs, 調(diào)用其中的哪個過程需要根據(jù)程序運(yùn)行的實(shí)際狀態(tài)來判斷,那么使用動態(tài)調(diào)用就是一個很好的選擇。

  使用動態(tài)調(diào)用,即使裝載一個DLLs失敗了,程序仍能繼續(xù)運(yùn)行。

  10.2.3 靜態(tài)調(diào)用

  在靜態(tài)調(diào)用一個DLLs中的過程或函數(shù)時,external指示增加到過程或函數(shù)的聲明語句中。被調(diào)用的過程或函數(shù)必須采用遠(yuǎn)調(diào)用模式。這可以使用far過程指示或一個{$F +}編譯指示。

  Delphi全部支持傳統(tǒng)Windows動態(tài)鏈接庫編程中的三種調(diào)用方式,它們是:

  ● 通過過程/函數(shù)名

  ● 通過過程/函數(shù)的別名

  ● 通過過程/函數(shù)的順序號

  通過過程或函數(shù)的別名調(diào)用,給用戶編程提供了靈活性,而通過順序號(Index)調(diào)用可以提高相應(yīng)DLL的裝載速度。

  10.2.4 動態(tài)調(diào)用

  10.2.4.1 動態(tài)調(diào)用中的API函數(shù)

  動態(tài)調(diào)用中使用的Windows API函數(shù)主要有三個,即:Loadlibrary,GetProcAddress和Freelibrary。

  1.Loadlibrary: 把指定庫模塊裝入內(nèi)存

  語法為:

  function Loadlibrary(LibFileName: PChar): THandle;

  LibFileName指定了要裝載DLLs的文件名,如果LibFileName沒有包含一個路徑,則Windows按下述順序進(jìn)行查找:

  (1)當(dāng)前目錄;

  (2)Windows目錄(包含win.com的目錄)。函數(shù)GetWindowDirectory返回這一目錄的路徑;

  (3)Windows系統(tǒng)目錄(包含系統(tǒng)文件如gdi.exe的目錄)。函數(shù)GetSystemDirectory返回這一目錄的路徑;

  (4)包含當(dāng)前任務(wù)可執(zhí)行文件的目錄。利用函數(shù)GetModuleFileName可以返回這一目錄的路徑;

  (5)列在PATH環(huán)境變量中的目錄;

  (6)網(wǎng)絡(luò)的映象目錄列表。

  如果函數(shù)執(zhí)行成功,則返回裝載庫模塊的實(shí)例句柄。否則,返回一個小于HINSTANCE_ERROR的錯誤代碼。錯誤代碼的意義如下表:

  表10.2 Loadlibrary返回錯誤代碼的意義

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

  錯誤代碼 意 義

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

  0 系統(tǒng)內(nèi)存不夠,可執(zhí)行文件被破壞或調(diào)用非法

  2 文件沒有被發(fā)現(xiàn)

  3 路徑?jīng)]有被發(fā)現(xiàn)

  5 企圖動態(tài)鏈接一個任務(wù)或者有一個共享或網(wǎng)絡(luò)保護(hù)錯

  6 庫需要為每個任務(wù)建立分離的數(shù)據(jù)段

  8 沒有足夠的內(nèi)存啟動應(yīng)用程序

  10 Windows版本不正確

  11 可執(zhí)行文件非法;蛘卟皇荳indows應(yīng)用程序,或者在.EXE映

  像中有錯誤

  12 應(yīng)用程序?yàn)橐粋不同的操作系統(tǒng)設(shè)計(如OS/2程序)

  13 應(yīng)用程序?yàn)镸S DOS4.0設(shè)計

  14 可執(zhí)行文件的類型不知道

  15 試圖裝載一個實(shí)模式應(yīng)用程序(為早期Windows版本設(shè)計)

  16 試圖裝載包含可寫的多個數(shù)據(jù)段的可執(zhí)行文件的第二個實(shí)例

  19 試圖裝載一個壓縮的可執(zhí)行文件。文件必須被解壓后才能被裝裁

  20 動態(tài)鏈接庫文件非法

  21 應(yīng)用程序需要32位擴(kuò)展

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

  假如在應(yīng)用程序用Loadlibrary調(diào)用某一模塊前,其它應(yīng)用程序已把該模塊裝入內(nèi)存,則Loadlibrary并不會裝載該模塊的另一實(shí)例,而是使該模塊的“引用計數(shù)”加1。

  2.GetProcAddress:撿取給定模塊中函數(shù)的地址

  語法為:

  function GetProcAddress(Module: THandle; ProcName: PChar): TFarProc;

  Module包含被調(diào)用的函數(shù)庫模塊的句柄,這個值由Loadlibrary返回。如果把Module設(shè)置為nil,則表示要引用當(dāng)前模塊。

  ProcName是指向含有函數(shù)名的以nil結(jié)尾的字符串的指針,或者也可以是函數(shù)的次序值。如果ProcName參數(shù)是次序值,則如果該次序值的函數(shù)在模塊中并不存在時,GetProcAddress仍返回一個非nil的值。這將引起混亂。因此大部分情況下用函數(shù)名是一種更好的選擇。如果用函數(shù)名,則函數(shù)名的拼寫必須與動態(tài)鏈接庫文件EXPORTS節(jié)中的對應(yīng)拼寫相一致。

  如果GetProcAddress執(zhí)行成功,則返回模塊中函數(shù)入口處的地址,否則返回nil。

  3.Freelibrary:從內(nèi)存中移出庫模塊

  語法為:

  procedure Freelibrary(Module : THandle);

  Module為庫模塊的句柄。這個值由Loadlibrary返回。

  由于庫模塊在內(nèi)存中只裝載一次,因而調(diào)用Freelibrary首先使庫模塊的引用計數(shù)減一。如果引用計數(shù)減為0,則卸出該模塊。

  每調(diào)用一次Loadlibrary就應(yīng)調(diào)用一次FreeLibray,以保證不會有多余的庫模塊在應(yīng)用程序結(jié)束后仍留在內(nèi)存中。

  10.2.4.2 動態(tài)調(diào)用舉例

  對于動態(tài)調(diào)用,我們舉了如下的一個簡單例子。系統(tǒng)一共包含兩個編輯框。在第一個編輯框中輸入一個字符串,而后在第二個編輯框中輸入字符。如果該字符包含在第一個編輯框的字符串中,則標(biāo)簽框顯示信息:“位于第n位。”,否則顯示信息:“不包含這個字符!。如圖是程序的運(yùn)行界面。

  輸入檢查功能的實(shí)現(xiàn)在Edit2的OnKeyPress事件處理過程中,程序清單如下。

  procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);

  var

  order: Integer;

  txt: PChar;

  PFunc: TFarProc;

  Moudle: THandle;

  begin

  Moudle := Loadlibrary('c:\dlls\example.dll');

  if Moudle > 32 then

  begin

  Edit2.text := '';

  Pfunc := GetProcAddress(Moudle,'Instr');

  txt := StrAlloc(80);

  txt := StrPCopy(txt,Edit1.text);

  Order := TInstr(PFunc)(txt,Key);

  if Order = -1 then

  Label1.Caption := '不包含這個字符 '

  else

  Label1.Caption := '位于第'+IntToStr(Order+1)+'位';

  end;

  Freelibrary(Moudle);

  end;

  在利用GetProcAddess返回的函數(shù)指針時,必須進(jìn)行強(qiáng)制類型轉(zhuǎn)換:

  Order := TInstr(PFunc)(text,Key);

  TInStr是一個定義好了的函數(shù)類型:

  type

  TInStr = function(Source: PChar;Check: Char): Integer;

  10.3 利用DLLs實(shí)現(xiàn)數(shù)據(jù)傳輸

  10.3.1 DLLs中的全局內(nèi)存

  Windows規(guī)定:DLLs并不擁有它打開的任何文件或它分配的任何全局內(nèi)存塊。這些對象由直接或間接調(diào)用DLLs的應(yīng)用程序擁有。這樣,當(dāng)應(yīng)用程序中止時,它擁有的打開的文件自動關(guān)閉,它擁有的全局內(nèi)存塊自動釋放。這就意味著保存在DLLs全局變量中的文件和全局內(nèi)存塊變量在DLLs沒有被通知的情況下就變?yōu)榉欠。這將給其它使用該DLLs的應(yīng)用程序造成困難。

  為了避免出現(xiàn)這種情況,文件和全局內(nèi)存塊句柄不應(yīng)作為DLLs的全局變量,而是作為DLLs中過程或函數(shù)的參數(shù)傳遞給DLLs使用。調(diào)用DLLs的應(yīng)用程序應(yīng)該負(fù)責(zé)對它們的維護(hù)。

  但在特定情況下,DLLs也可以擁有自己的全局內(nèi)存塊。這些內(nèi)存塊必須用gmem_DDEShare屬性進(jìn)行分配。這樣的內(nèi)存塊直到被DLLs顯示釋放或DLLs退出時都保持有效。

  由DLLs管理的全局內(nèi)存塊是應(yīng)用程序間進(jìn)行數(shù)據(jù)傳輸?shù)挠忠煌緩,下面我們將專門討論這一問題。

  10.3.2 利用DLLs實(shí)現(xiàn)應(yīng)用程序間的數(shù)據(jù)傳輸

  利用DLLs實(shí)現(xiàn)應(yīng)用程序間的數(shù)據(jù)傳輸?shù)牟襟E為:

  1. 編寫一個DLLs程序,其中擁有一個用gmem_DDEShare屬性分配的全局內(nèi)存塊;

  2. 服務(wù)器程序調(diào)用DLLs,向全局內(nèi)存塊寫入數(shù)據(jù);

  3. 客戶程序調(diào)用DLLs,從全局內(nèi)存塊讀取數(shù)據(jù)。

  10.3.2.1 用于實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)腄LLs的編寫

  用于實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)腄LLs與一般DLLs的編寫基本相同,其中特別的地方是:

  1. 定義一個全局變量句柄:

  var

  hMem: THandle;

  2. 定義一個過程,返回該全局變量的句柄。該過程要包含在exports子句中。如:

  function GetGlobalMem: THandle; export;

  begin

  Result := hMem;

  end;

  3. 在初始化代碼中分配全局內(nèi)存塊:

  程序清單如下:

  begin

  hMem := GlobalAlloc(gmem_MOVEABLE and gmem_DDEShare,num);

  if hMem = 0 then

  MessageDlg('Could not allocate memory',mtWarning,[mbOK],0);

  end.

  num是一個預(yù)定義的常數(shù)。

  Windows API函數(shù)GlobalAlloc用于從全局內(nèi)存堆中分配一塊內(nèi)存,并返回該內(nèi)存塊的句柄。該函數(shù)包括兩個參數(shù),第一個參數(shù)用于設(shè)置內(nèi)存塊的分配標(biāo)志?梢允褂玫姆峙錁(biāo)志如下表所示。

上一頁  1 2 3 4 5 下一頁
  相關(guān)推薦:2010年9月計算機(jī)等級考試試題及答案解析專題
       預(yù)告:名師解析2010年9月計算機(jī)等級考試試題答案
       2010年9月計算機(jī)等級考試成績查詢時間及入口
       2010年9月計算機(jī)等考成績查詢短信免費(fèi)提醒開通
文章搜索
計算機(jī)等級考試欄目導(dǎo)航
版權(quán)聲明:如果計算機(jī)等級考試網(wǎng)所轉(zhuǎn)載內(nèi)容不慎侵犯了您的權(quán)益,請與我們聯(lián)系800@exam8.com,我們將會及時處理。如轉(zhuǎn)載本計算機(jī)等級考試網(wǎng)內(nèi)容,請注明出處。