52
技術社區[雲棲]
C/C++回調函數
回調函數就像您隨身帶的BP機:告訴別人號碼,在它有事情時Call您回調用於層間協作,上層將本層函數安裝在下層,這個函數就是回調,而下層在一定條件下觸發回調,例如作為一個驅動,是一個底層,他在收到一個數據時,除了完成本層的處理工作外,還將進行回調,將這個數據交給上層應用層來做進一步處理,這在分層的數據通信中很普遍。
其實回調和API非常接近,他們的共性都是跨層調用的函數。但區別是API是低層提供給高層的調用,一般這個函數對高層都是已知的;而回調正好相反,他是高層提供給低層的調用,對於低層他是未知的,必須由高層進行安裝,這個安裝函數其實就是一個低層提供的API,安裝後低層不知道這個回調的名字,但它通過一個函數指針來保存這個回調,在需要調用時,隻需引用這個函數指針和相關的參數指針。
其實:回調就是該函數寫在高層,低層通過一個函數指針保存這個函數,在某個事件的觸發下,低層通過該函數指針調用高層那個函數。回調在C語言中是通過函數指針來實現的,通過將回調函數的地址傳給被調函數從而實現回調。因此,要實現回調,必須首先定義函數指針,請看下麵的例子:
void Func(char *s);// 函數原型
void (*pFunc) (char *);//函數指針
可以看出,函數的定義和函數指針的定義非常類似。
一般的化,為了簡化函數指針類型的變量定義,提高程序的可讀性,我們需要把函數指針類型自定義一下。
typedef void(*pcb)(char *);
回調函數可以象普通函數一樣被程序調用,但是隻有它被當作參數傳遞給被調函數時才能稱作回調函數。
被調函數的例子:
例一:
void GetCallBack(pcb callback)
{
/*do something*/
}
用戶在調用上麵的函數時,需要自己實現一個pcb類型的回調函數:
void fCallback(char *s)
{
/* do something */
}
然後,就可以直接把fCallback當作一個變量傳遞給GetCallBack,
GetCallBack(fCallback);
如果賦了不同的值給該參數,那麼調用者將調用不同地址的函數。賦值可以發生在運行時,這樣使你能實現動態綁定。
例二:
//Test.c
#include <stdlib.h>
#include <stdio.h>
int Test1()
{
int i;
for (i=0; i<30; i++)
{
printf(“The %d th charactor is: %c\n”, i, (char)(‘a' + i%26));
}
return 0;
}
int Test2(int num)
{
int i;
for (i=0; i<num; i++)
{
printf(“The %d th charactor is: %c\n”, i, (char)('a' + i%26));
}
return 0;
}
void Caller1(void (*ptr)()) //指向函數的指針作函數參數
{
(*ptr)();
}
void Caller2(int n, int (*ptr)()) //指向函數的指針作函數參數,這裏第一個參數是為指向函數的指針服務的,
{ //不能寫成void Caller2(int (*ptr)(int n)),這樣的定義語法錯誤。
(*ptr)(n);
return;
}
int main()
{
printf(“************************\n”);
Caller1(Test1); //相當於調用Test2();
printf(“&&&&&&************************\n”);
Caller2(30, Test2); //相當於調用Test2(30);
return 0;
}
以上通過將回調函數的地址傳給調用者從而實現調用,但是需要注意的是帶參回調函數的用法。要實現回調,必須首先定義函數指針。函數指針的定義這裏稍微提一下。比如:
int (*ptr)(); 這裏ptr是一個函數指針,其中(*ptr)的括號不能省略,因為括號的優先級高於星號,那樣就成了一個返回類型為整型的函數聲明了
最後更新:2017-04-02 15:15:00