函式名作為引數傳遞 與 回撥函式
成員函式名不能作為引數傳遞,否則會發生錯誤,因為裡面隱藏著一個this 指標
回撥函式,就是由你自己寫的。你需要呼叫另外一個函式,而這個函式的其中一個引數,就
是你的這個回撥函式名。這樣,系統在必要的時候,就會呼叫你寫的回撥函式,這樣你就可
以在回撥函式裡完成你要做的事。
模組A有一個函式foo,它向模組B傳遞foo的地址,然後在B裡面發生某種事件(event)時,通過從A裡面傳遞過來的foo的地址呼叫foo,通知A發生了什麼事情,讓A作出相應反應。 那麼我們就把foo稱為回撥函式。
例子:
回撥函式是一個很有用,也很重要的概念。當發生某種事件時,系統或其他函式將會自動呼叫你定義的一段函式。回撥函式在windows程式設計使用的場合很多,比如Hook回撥函式:MouseProc,GetMsgProc以及EnumWindows,DrawState的回撥函式等等,還有很多系統級的回撥過程。本文不準備介紹這些函式和過程,而是談談實現自己的回撥函式的一些經驗。
之所以產生使用回撥函式這個想法,是因為現在使用VC和Delphi混合程式設計,用VC寫的一個DLL程式進行一些時間比較長的非同步工作,工作完成之後,需要通知使用DLL的應用程式:某些事件已經完成,請處理事件的後續部分。開始想過使用同步物件,檔案影射,訊息等實現DLL函式到應用程式的通知,後來突然想到可不可以在應用程式端先寫一個函式,等需要處理後續事宜的時候,在DLL裡直接呼叫這個函式即可。
於是就動手,寫了個回撥函式的原形。在VC和 Delphi裡都進行了測試
一:宣告回撥函式型別。
vc版
typedef int (WINAPI *PFCALLBACK)(int Param1,int Param2) ;
二:宣告回撥函式原形
宣告函式原形
vc版
int WINAPI CBFunc(int Param1,int Param2);
三: 回撥函式呼叫呼叫者
呼叫回撥函式的函式我把它放到了DLL裡,這是一個很簡單的VC生成的WIN32 DLL.並使用DEF檔案輸出其函式名 TestCallBack。實現如下:
PFCALLBACK gCallBack=0;
void WINAPI TestCallBack(PFCALLBACK Func)
{
if(Func==NULL)return;
gCallBack=Func;
DWORD ThreadID=0;
HANDLE hThread = CreateThread( NULL, NULL, Thread1, LPVOID(0), &ThreadID );
return;
}
此函式的工作把傳入的 PFCALLBACK Func引數儲存起來等待使用,並且啟動一個執行緒。宣告瞭一個函式指標PFCALLBACK gCallBack儲存傳入的函式地址。
四: 回撥函式如何被使用:
TestCallBack函式被呼叫後,啟動了一個執行緒,作為演示,執行緒人為的進行了延時處理,並且把執行緒執行的過程列印在螢幕上.
五:萬事具備
使用vc和Delphi各建立了一個工程,編寫回撥函式的實現部分
VC版
int WINAPI CBFunc(int Param1,int Param2)
{
int res= Param1+Param2;
TCHAR Buffer[256]="";
sprintf(Buffer,"callback result = %d",res);
MessageBox(NULL,Buffer,"Testing",MB_OK); //演示回撥函式被呼叫
return res;
}
Delphi版
function CBFunc(Param1,Param2:integer):integer;
begin
result:= Param1+Param2;
TForm1.Edit1.Text:=inttostr(result); / /演示回撥函式被呼叫
end;
使用靜態連線的方法連線DLL裡的出口函式 TestCallBack,在工程裡新增 Button( 對於Delphi的工程,還需要在Form1上放一個Edit控制元件,預設名為Edit1)。
響應ButtonClick事件呼叫 TestCallBack
TestCallBack(CBFunc) //函式的引數CBFunc為回撥函式的地址
函式呼叫建立執行緒後立刻返回,應用程式可以同時幹別的事情去了。現在可以看到螢幕上不停的顯示字串,表示dll裡建立的執行緒執行正常。一會之後,執行緒延時部分結束結束,vc的應用程式彈出MessageBox,表示回撥函式被呼叫並顯示根據Param1,Param2運算的結果,Delphi的程式edit控制元件裡的文字則被改寫成Param1,Param2 的運算結果。
可見使用回撥函式的程式設計模式,可以根據不同的需求傳遞不同的回撥函式地址,或者定義各種回撥函式的原形(同時也需要改變使用回撥函式的引數和返回值約定),實現多種回撥事件處理,可以使程式的控制靈活多變,也是一種高效率的,清晰的程式模組之間的耦合方式。在一些非同步或複雜的程式系統裡尤其有用 -- 你可以在一個模組(如DLL)裡專心實現模組核心的業務流程和技術功能,外圍的擴充套件的功能只給出一個回撥函式的介面,通過呼叫其他模組傳遞過來的回撥函式地址的方式,將後續處理無縫地交給另一個模組,隨它按自定義的方式處理。
本文的例子使用了在DLL裡的多執行緒延時後呼叫回撥函式的方式,只是為了突出一下回撥函式的效果,其實只要是在本程式之內,都可以隨你高興可以把函式地址傳遞來傳遞去,當成回撥函式使用。
這樣的程式設計模式原理非常簡單單一:就是把函式也看成一個指標一個地址來呼叫,沒有什麼別的複雜的東西,僅僅是程式設計裡的一個小技巧。至於回撥函式模式究竟能為你帶來多少好處,就看你是否使用,如何使用這種程式設計模式了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10697500/viewspace-612406/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- setInterval 回撥函式傳引數函式
- 函式作為引數傳遞函式
- JavaScript函式傳遞引數JavaScript函式
- 函式的引數傳遞函式
- JavaScript函式引數傳遞JavaScript函式
- 回撥函式 與 函式閉包函式
- 函式引數傳遞及返回函式
- JavaScript為事件處理函式傳遞引數JavaScript事件函式
- Golang 切片作為函式引數傳遞的陷阱與解答Golang函式
- 回撥函式函式
- 回撥函式,求積函式函式
- python函式之引數傳遞Python函式
- 函式指標&回撥函式Callback函式指標
- js中函式引數值傳遞和引用傳遞JS函式
- JavaScript 回撥函式JavaScript函式
- JavaScript回撥函式JavaScript函式
- JS—回撥函式JS函式
- 動畫回撥函式動畫函式
- java回撥函式Java函式
- 回撥函式(CallBack)函式
- python中函式的引數傳遞Python函式
- php函式引用傳遞引數的方法PHP函式
- JavaScript 事件處理函式傳遞引數JavaScript事件函式
- onclick事件處理函式傳遞引數事件函式
- JavaScript:鉤子函式與回撥函式的區別JavaScript函式
- C語言函式指標與回撥用函式C語言函式指標
- 【C語言】函式的概念和函式的呼叫(引數傳遞)C語言函式
- JS閉包函式和回撥函式JS函式
- Python的函式引數傳遞:傳值?引用?Python函式
- 『無為則無心』Python函式 — 26、Python函式引數的傳遞方式Python函式
- Python語法—函式及引數傳遞Python函式
- Promise中多個回撥函式之間的資料傳遞Promise函式
- 回撥函式的作用函式
- TLS回撥函式(Note)TLS函式
- java 回撥函式示例Java函式
- Python回撥函式Python函式
- android回撥函式Android函式
- 函式回撥(C++)函式C++