回調函數(運用)

一、定義

什麼是回調函數?它首先是一個函數,這是肯定的,我舉個例子:有兩個函數A和B,首先應用程序將A的地址告訴B,這稱之爲註冊回調函數,B在收到外部某個命令的時候,可以根據B的地址來調用A,這個先被傳入B,後面又被B調用的函數A就稱之爲回調函數

這樣看來,判斷一個函數是不是回調函數是從它被調用的方式來定義的,那麼B函數一般來說需要一個傳入參數,參數類型是函數指針。

二、應用場景

有人可能會說,B想調用A直接在函數裏面直接調用就好了,爲什麼先要把A的地址作爲一個參數傳給B這麼麻煩呢?

我們可以設想這樣一個生活場景:

商場裏有一款商品賣的特別好,經常賣斷貨,許多客戶都要求新貨一到就馬上聯繫他們,爲了商場能聯繫上客戶,客戶們就把自己的聯繫方式告訴商場(註冊回調函數),客戶A把自己的手機號告訴了商場,客戶B呢把自己的郵箱告訴了商場。等到新貨到了,商場就打電話(調用回調函數)通知客戶A,而通知客戶B則通過發郵件(調用回調函數)。

這裏我們可以看到,客戶把自己的聯繫方式告訴商場,至於是什麼聯繫方式商場並不關心,只要能聯繫上客戶就行,這樣就給客戶很大的靈活性。

再看一個具體的應用場景:

一個管理USB接口的模塊,這個模塊會不停的檢測USB接口是否有U盤插入。而當有U盤插入的這個事件發生時,不同的用戶可能想幹不同的事,比如有的用戶想在屏幕上顯示“有U盤插入了”,而有的用戶就想讓一個喇叭不停的響等等。那麼這個時候用戶只要把U盤插入響應函數的地址告訴模塊(註冊回調函數),等到模塊檢測到有U盤插入就去調用這個響應函數(調用回調函數),至於這個函數做些什麼,模塊並不關心,這就增加了用戶的靈活性,實現用戶想要的功能。

三、怎麼用

從上面我們看到需要把回調函數的地址作爲一個參數註冊到模塊中,這個函數地址其實就是個函數指針,既然要註冊到模塊中,這個回調函數必須以該模塊認可的格式編寫,說的比較抽象,下面舉個例子說明下。

先寫模塊部分,構造一個結構體

typedef struct _CheckEvent()
{
  int eventID;
  BOOL (*Check)(void);
}CheckEvent;

上面的結構體中定義了一個函數指針Check,參數是void,函數類型是BOOL,這就要求用戶定義的回調函數也必須是參數爲void、類型爲BOOL的函數。

void Module(void)
{
  int index,id;
  while(1)
  {
    id=GetEventID(); 
    for(index=0;index<2;index++)
    {
      if(id == arrayCheckEvent[index]. eventID)//當事件eventID發生時
      arrayCheckEvent[index]. Check();//調用eventID對應的回調函數
    }
  }
 }

接着定義一個CheckEvent的數組:

CheckEvent arrayCheckEvent[2]=
 {
   {0, CheckEvent0},//註冊回調函數CheckEvent0
   {1, CheckEvent1}//註冊回調函數CheckEvent1
 };

編寫模塊主功能:

應用程序要做的就是實現回調函數

BOOL CheckEvent0(void)和BOOL CheckEvent1(void)了,實現用戶想要的功能,注意回調函數的參數和函數類型要和模塊中定義的CheckEvent結構體中的函數指針定義的一致。

作者: 心飛揚

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章