Delphi基礎(chǔ) 回調(diào)函數(shù)及其使用
“回調(diào)機(jī)制”是window 在執(zhí)行某個(gè)API函數(shù)的過程中,調(diào)用指定的一個(gè)函數(shù)(回調(diào)函數(shù))。
比如:你有一個(gè)任務(wù),但是有一部分你不會(huì)做,或者說不愿做,所以我來幫你做這部分,你做你其它的任務(wù)工作或者等著我的消息,但是當(dāng)我完成的時(shí)候我要通知你我做好了,你可以用了,我怎么通知你呢?你給我一部手機(jī),讓我做完后給你打電話,我就打給你了,你拿到我的成果加到你的工作中,繼續(xù)完成其它的工作.這就叫回叫,手機(jī)是我通知你的手段,它就是回叫函數(shù),也叫回調(diào)函數(shù)(Callback Function)。
簡(jiǎn)單說就是,由程序員編寫的,給windows系統(tǒng)(API)調(diào)用的函數(shù)。 也就是說,函數(shù)的功能有你定,調(diào)用有windows系統(tǒng)(API)調(diào)用。
回調(diào)函數(shù)就是通過函數(shù)的指針來調(diào)用的函數(shù)。對(duì)于一個(gè)傳遞給其他函數(shù)的參數(shù),如果你傳遞的是一個(gè)函數(shù)的指針(也就是地址),當(dāng)這個(gè)指針被用來調(diào)用這個(gè)函數(shù)時(shí),就可以說是構(gòu)造了一個(gè)回調(diào)函數(shù)。就是你把自定義函數(shù)地址給別人,別人調(diào)用你的函數(shù)。
回調(diào)函數(shù),就是由你自己寫的。你需要調(diào)用另外一個(gè)函數(shù),而這個(gè)函數(shù)的其中一個(gè)參數(shù),就是你的這個(gè)回調(diào)函數(shù)名。這樣,系統(tǒng)在必要的時(shí)候,就會(huì)調(diào)用你寫的回調(diào)函數(shù),這樣你就可以在回調(diào)函數(shù)里完成你要做的事。
1. 回調(diào)函數(shù)是由開發(fā)者按照一定的原型進(jìn)行定義的函
2. 回調(diào)函數(shù)并不由開發(fā)者直接調(diào)用執(zhí)行
3 .回調(diào)函數(shù)通常作為參數(shù)傳遞給系統(tǒng)API,由該API來調(diào)用。
4. 回調(diào)函數(shù)可能被系統(tǒng)API調(diào)用一次,也可能被循環(huán)調(diào)用多次。
回調(diào)函數(shù)主要用于一些比較費(fèi)時(shí)的操作,或響應(yīng)不知道何時(shí)將會(huì)發(fā)生的事件,回調(diào)函數(shù)提供了一種異步的機(jī)制,相對(duì)于同步執(zhí)行,提高了效率.
前者的例子如WriteFileEx,ReadFileEx等,函數(shù)的***一個(gè)參數(shù)是一個(gè)回調(diào)函數(shù)的指針,程序中調(diào)用WriteFileEx以后,就直接返回了,可以繼續(xù)進(jìn)行其他工作,系統(tǒng)在讀寫操作完成后通知程序作善后處理.后者的例子就是windows的事件機(jī)制回調(diào)函數(shù)的另一個(gè)用途,是用于一些枚舉函數(shù),如EnumDisplayModes等,每找到一種支持的顯示模式,就通知回調(diào)函數(shù),由回調(diào)函數(shù)具體處理,這是因?yàn)?EnumDisplayModes本身并不知道用戶要如何處理.能,用戶提供回調(diào)函數(shù),定制系統(tǒng)的功能,這樣,不同的用戶提供不同的回調(diào)函數(shù),可以使系統(tǒng)具有不同的功能.
這就是所謂的plugin.使用回調(diào)函數(shù)實(shí)際上就是在調(diào)用某個(gè)函數(shù)(通常是API函數(shù))時(shí),將自己的一個(gè)函數(shù)(這個(gè)函數(shù)為回調(diào)函數(shù))的地址作為參數(shù)傳遞給那個(gè)函數(shù)。而那個(gè)函數(shù)在需要的時(shí)候,利用傳遞的地址調(diào)用回調(diào)函數(shù),這時(shí)你可以利用這個(gè)機(jī)會(huì)在回調(diào)函數(shù)中處理消息或完成一定的操作。至于如何定義回調(diào)函數(shù),跟具體使用的API函數(shù)有關(guān),一般在幫助中有說明回調(diào)函數(shù)的參數(shù)和返回值等。
1。比如在內(nèi)核編程中,驅(qū)動(dòng)程序就要提供一些回調(diào)函數(shù),當(dāng)一個(gè)設(shè)備的數(shù)據(jù)讀寫完成后,讓系統(tǒng)調(diào)用這些回調(diào)函數(shù)來執(zhí)行一些后續(xù)工作。
2?;卣{(diào)函數(shù)和其他函數(shù)沒什么區(qū)別,只是有固定的參數(shù)和調(diào)用約定,比如windows的回掉函數(shù)都要用stdcall. 參數(shù)是由調(diào)用這個(gè)回調(diào)函數(shù)的函數(shù)傳遞的,當(dāng)然要規(guī)定好參數(shù)格式。使用很簡(jiǎn)單,就是傳遞這個(gè)回調(diào)函數(shù)的地址給調(diào)用的函數(shù)作為一個(gè)參數(shù)。比如創(chuàng)建線程的時(shí)候就是這樣的 。
3。回調(diào)函數(shù)的使用主要在于windows原有的API函數(shù),但對(duì)于用戶的自定義的調(diào)用函數(shù)一般在于動(dòng)態(tài)連接庫(kù)中。常規(guī)的同一個(gè)工程下面一般不需要使用回調(diào)函數(shù)。(個(gè)人認(rèn)為).。
使用回調(diào)函數(shù)需要注意的地方:
1、 定義一個(gè)回調(diào)函數(shù)類型,跟一般的函數(shù)過程的定義并沒有什么區(qū)別,但其定義必須根據(jù)需要滿足回調(diào)函數(shù)的函數(shù)要求,唯一的區(qū)別在于在函數(shù)或過程的定義后面必須聲明其為windows標(biāo)準(zhǔn)調(diào)用;
例:
對(duì)于函數(shù)的聲明:
type
- THDFunction= function(I:integer;s:string):integer; stdcall;
對(duì)于過程的聲明:
type
- THDProcedure=procedure(s:string); stdcall;
2、 然后根據(jù)此原形定義一個(gè)相應(yīng)的函數(shù)或過程,對(duì)于這個(gè)函數(shù)或過程來說名字沒有什么要求,對(duì)函數(shù)其參數(shù)的類型和返回值的類型必須和定義的回調(diào)函數(shù)類型完全一致,對(duì)于過程來說,只需要其參數(shù)類型一樣就可以了。
例:根據(jù)上面的函數(shù)和過程的原形定義一個(gè)相應(yīng)的函數(shù)和一個(gè)相應(yīng)的過程。
函數(shù)原形定義:
- Function HdFunExample(k:integer,sExam:string):integer; stdcall;
過程定義:
- procedure HdProExample(sExam:string);stdcall;
3、 在程序中實(shí)現(xiàn)此回調(diào)函數(shù)或著過程;
- Function HdFunExample(k:integer,sExam:string):integer; stdcall;
- Begin
- End;
- procedure HdProExample(sExam:string);stdcall;
- begin
- end;
4、 調(diào)用過程;
回調(diào)函數(shù)一般作為系統(tǒng)的某個(gè)函數(shù)的入口地址;
根據(jù)調(diào)用函數(shù)的原形:
假設(shè)有如下調(diào)用函數(shù):
- function DyHdFunExample(HdFun:THDFunction;I:integer):boolean;
注:
在調(diào)用函數(shù)中通過對(duì)函數(shù)指針的處理可以直接調(diào)用回調(diào)函數(shù)(即調(diào)用函數(shù)中的那個(gè)是回調(diào)函數(shù)類型的參數(shù),直接操作它),使回調(diào)函數(shù)履行一定的操作。即在調(diào)用函數(shù)中實(shí)現(xiàn)回調(diào)函數(shù)的功能。
調(diào)用:
- var
- I:integer;
- begin
- I:=DyHdFunExample(@HdFunExample,i);
- //…….
- End;
【編輯推薦】