在Z-Stack中大量使用了回调函数,例如OnBoard_KeyCallback,Onboard_TimerCallBack,这些都是回调函数,以前没有接触过回调函数,看来自己掌握的知识还是少啊,据说在C++中,VC++中经常用到,特别是在STL中也是大量使用了回调函数,看来回调函数的用处还是很大的。为了搞清楚回调函数是什么,以及怎么使用,在网上搜集了一些资料,基本上搞清楚了回调函数。
回调函数从字面上可以看出,它一定是一个函数,但是这个函数有什么特别之处呢?孤立的单看这个函数基本和普通的函数没有什么区别,关键是在使用上,也就是调用这个回调函数的函数会有一些特别,特别之处就在于一般情况下,调用回调函数的函数(这里称之为B函数)中的参数,其中之一是函数的指针,并且在B函数中要使用到回调函数。这样和别的函数整个联系起来,才真正的构成了回调函数。孤立看一个函数是看不出这个函数是不是回调函数时,当然也可以通过看函数的名字看出来,呵呵!其实,回调函数就是函数指针的一种用法。只是这种用法把有些细节封装了。
回调函数一般是由编程人员自己写的。这里有一个例子,假设有一个快速排序的函数,快速排序需要首先比较两个数的大小,那这两个数可能是int型,char型,long型,如果都放到了快速排序函数处理这样类型,那么函数就会显得通用性不够,这时就可以使用回调函数了,就是程序自己写一个函数,这个函数用来比较数的大小,而快速排序函数只需要做的就是在函数的参数列表中,有一个函数的指针,这个函数指针中有两个指针参数,然后,在快速排序中就根据这个回调函数的返回结果来判断两个数的大小。当我们要使用这个排序算法时,其实在这个排序算法中也使用了我们自己的一个函数,那这个函数就是回调函数,当然,这个例子还是有点勉强,也可以使用C++的模板把类型封装起来,也应该是一种很好的方法。只不过我的C++学的实在不尽人入意。这里只是为了说明这种情况。
其实,在调用回调函数的函数(B函数)中,其中一个参数是函数的指针,那么这个函数指针中也有一定的参数。也就是说只要符合我这个B函数中函数指针的格式,都可以当作回调函数,B函数并不关心你这个函数是实现什么功能的。那这个回调函数的实现就交给了程序员,程序员可以在程序中定义不同的功能。这就相当主一个公式,就按格式套用就可以了。
这里有一个很简单的回调函数。
#include
void printWelcome(int len)
{
printf("Welcom -- %d\n", len);
}
void printGoodbye(int len)
{
printf("Goodbye -- %d\n", len);
}
void callback(int times, void (* print)(int))
{
int i;
for (i = 0; i < times; ++i)
{
print(i);
}
}
void main(void)
{
callback(10, printWelcome);
callback(10, printGoodbye);
printWelcome(5);
}
在网上找了一篇用分层的概念来解释了回调机制:callback函数为B层,main函数和print*函数为A层,A层调用了B层的回调函数callmeback,而B层的回调函数调用了A层的实现函数print*。说白了B层就是一个接口。
说了这么多似乎和我们的Z-Stack协议栈没有任何的联系,下面就以一个按键的回调函数为例,看看在其中是怎么使用回调函数的。其中,协议中和定时器,UART口等很多地方都使用了回调函数,正确理解回调函数也有助于理解协议的流程。其实下面这张图,不仅可以表示出回调函数,还可以表现出Key事件是怎么触发的。
阅读(1045) | 评论(0) | 转发(0) |