提到回调函数,我也顺手在网上翻了一下,我发现说的都比较详细甚至于冗长了。很多人的解说都比较类似,回想当初自己刚接触的时候,我打算从一个非常简单的角度用几段话说完回调函数的使用和理解。
重点来了:什么是回调函数?
在程序中把你的函数换成函数指针,用指针去替代你本该写的函数名,这个被替代的函数就是回调函数。
结束!
用个简单的代码演示一下
//这里是它的头文件 Led.h
#ifndef __LED_H__
#define __LED_H__
void Led_On(void);
#endif
//这里是一个文件 Led.c
//这是一个函数,假设它有个功能,就是点亮LED灯
void Led_On(void)
{
LED = TRUE;
}
这里有另一个程序文件
//这里是它的头文件
#ifndef __SWITCH_H__
#define __SWITCH_H__
#include "Led.h" //方法一,引用LED头文件
void Get_Switch_State(void);
#endif
//这里是另一个文件 switch.c
//这里有另一个函数,假设它检测到某信号后需要点亮LED灯和处理一些事情;
extern void Led_On(void); //方法二,外部申明一下Led_On函数,如此才能跨函数调用
void Get_Switch_State(void)
{
if (Signel == TRUE)
Led_On(); //调用Led_On()函数,实现点亮LED功能
//.......
//do something
}
/* 要想能正常调用Led_On()函数,必须使用以上两个方法之一
*/
上面就是一个普通的程序流程,流程中有个普通的函数调用,如果,我将Get_Switch_State()中的Led_On()更换成指向Led_On()函数的函数指针,那么这时候Led_On就成了回调函数。
还是在另一个程序文件中
//这里是它的头文件
#ifndef __SWITCH_H__
#define __SWITCH_H__
#typedef void(*pFun)(void); //函数指针原型定义 重点一
void Get_Switch_State(void);
void CallBack_Reg(pFun cb);
#endif
//这里是另一个文件 switch.c
//这里有另一个函数,假设它检测到某信号后需要点亮LED灯和处理一些事情;
pFun CallBack_Ptr; //定义一个函数指针 重点二
//回调函数的注册函数CallBack_Reg()
void CallBack_Reg(pFun cb)
{
if (CallBack_Ptr == 0) //为函数指针赋值,当然它首先要没有被赋值
CallBack_Ptr = cb;
}
void Get_Switch_State(void)
{
if (Signel == TRUE)
CallBack_Ptr(); //调用Led_On()函数的指针,实现点亮LED功能 重点三
//.......
//do something
}
/* 发现关键点没有? switch.c 中再也没有出现Led_On();那它如何实现调用?
答案是还需要在其它地方
比如说main函数中把Led_On()函数和CallBack_Ptr 这个指针绑定一下
*/
void main(void)
{
Gpio_Init();
Bsp_Init();
Timer_Init();
CallBack_Reg(Led_On); //重点四
while (1)
{
.......
}
}
从上面的代码中可以明显发现几个特点
1.switch.c和.h中没有出现Led_On()函数了。 Led_On()函数被函数指针CallBack_Ptr替代了。
2.switch.c和.h中没有在引用文件Led.h了,实现了两个c文件的解耦,使他们的关联性降低了。
此时函数Led_On()就可以被称作 回调函数 了。
讲解完毕~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~