关键词:
1 定义和使用场合
回调函数是指 使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,就是由别人的函数运行期间来回调你实现的函数。
这一设计允许了底层代码调用在高层定义的子程序(如图1-1所示)。C语言中回调函数主要通过函数指针的方式实现。
回调的用途十分广泛:[1]
例如,假设有一个函数,其功能为读取配置文件并由文件内容设置对应的选项。若这些选项由散列值(hash function)所标记,则让这个函数接受一个回调会使得程序设计更加灵活:函数的调用者可以使用所希望的散列算法,该算法由一个将选项名转变为散列值的回调函数实现;因此,回调允许函数调用者在运行时调整原始函数的行为。
回调的另一种用途在于处理信号量。例如一个POSIX程序可能在收到SIGTERM信号时不愿立即终止;为了保证一切运行良好,该程序可以将清理函数注册为SIGTERM信号对应的回调。
回调亦可以用于控制一个函数是否作为:Xlib允许自定义的谓词(NSPredicate)用于决定程序是否希望处理特定的事件。
#include
#include
using namespace std;
typedef void (*FP)(char* s); //结构体表示函数指针
void f1(char* s)cout<<s;
void f2(char* s)cout<<s;
void f3(char* s)cout<<s;
int main(int argc,char* argv[])
int funcselector=0; //定义一个整数用于控制待执行的函数
void* a[]=f1,f2,f3; //定义了指针数组,这里a是一个普通指针
a[0]("Hello World! "); //编译错误,指针数组不能用下标的方式来调用函数
FP f[]=f1,f2,f3; //定义一个函数指针的数组,这里的f是一个函数指针
//此处用于处理funselector,控制待执行的函数
f[funselector]("Hello World! "); //正确,函数指针的数组进行下标操作可以进行函数的间接调用
return 0;
上面一个例子中提现了回调函数的部分作用。这里f1,f2,f3表示三个功能不相同的函数(举例说明:f1实现最大值输出,f2实现平均值输出,f3实现最小值输出)。总结一下回调函数的一些优势:
采用funcselector作为标志量,选择待执行的函数很方便的控制了函数的流程和工序。
f1,f2,f3三个特定函数模块化明显,便于设计者去维护、修改。如图1-1所示,很多系统中software library会完全封装,这样开发者只能通过回调函数去修改函数功能。
分析函数思路更加清晰,在lwip中大量使用回调函数,开发者可以根据回调函数的调用流程分析系统结构。
2 结构解析
回调函数主要结构有三部分组成:主函数、调用函数和被调函数(如图1-1所示)。C语言中,被调函数通常以函数指针(指向对应函数的入口地址)的形式出现。
这里给出一个最简单的回调函数结构,并解析相关数据结构。
//定义回调函数 void PrintfText() printf("Hello World! "); //定义实现回调函数的"调用函数" void CallPrintfText(void (*callfuct)()) callfuct(); //实现函数回调 int main(int argc,char* argv[]) CallPrintfText(PrintfText); return 0;
调用函数向其函数中传递 void (*callfuct)(void) 这是一个 void callfuct(void) 函数的入口地址,即PC指针可以通过移动到该地址执行void callfuct(void) 函数,可以通过类比数组来理解。
实现函数调用中,函数调用了“调用函数”,再在其中进一步调用被“调用函数”。相比于主函数直接调用“被调函数”,这种方法为使用者,而不是开发者提供了灵活的接口。另外,函数入口可以像变量一样设定同样为开发者提供了灵活性。
3 实例分析
这里分析一个lwip中较为复杂的回调函数使用范例:
void httpd_init(void) struct tcp_pcb * pcb; pcb = tcp_new(); tcp_bind(pcb,IP_ADDR_ANY,80); pcb = tcp_listen(pcb); tcp_accept(pcb, http_accept); void tcp_accept(struct tcp_pcb * pcb, err_t(* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) static err_t http_accept(void *arg, struct tcp_pcb * pcb, err_t err) tcp_setprio(pcb, TCP_PRIO_MIN); tcp_recv(pcb, http_recv); return ERR_OK; void tcp_recv(struct tcp_pcb * pcb, err_t (* recv)(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t err)) static err_t http_recv(void *arg, struct tcp_pcb * pcb, struct pbuf *p, err_t err)
这里调用两个回调函数,模块化分离了tcp和http,感兴趣可以看看lwip的RAW部分。
什么是回调函数(代码片段)
回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码。在JavaScript中函数也是对象的一种,同样对象可以作为参数传递给函数,因此函数也可以作为参数传... 查看详情
python回调函数用法实例(代码片段)
Python回调函数用法实例 回调函数 “回调函数就是一个通过函数指针调用的函数。 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。&rdqu... 查看详情
javascript回调函数(代码片段)
markdownjs-回调函数(代码片段)
javascriptjs回调函数(代码片段)
markdownjs回调函数(代码片段)
javascripttweenlite回调函数(代码片段)
回调函数示例讲解(代码片段)
1.什么是回调函数关于回调函数的定义,可以自行Wikipedia,但是我觉得官方的都太晦涩,看了还是弄不懂。这里给出在一个帖子上看到的定义,本人觉得比较好理解。函数F1调用函数F2的时候,函数F1通过参数给函数F2传递了另外... 查看详情
回调函数(代码片段)
functiona(parmse,()=> 执行代码)回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。回调方法是任何一个被以该回调方法为其第一个参数的其它方法... 查看详情
回调函数(代码片段)
functiona(parmse,()=> 执行代码)回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。回调方法是任何一个被以该回调方法为其第一个参数的其它方法... 查看详情
htmlajax_回调函数(代码片段)
03回调函数(代码片段)
//回调函数doSomeThing(result=>doSomeThingElse(result,newResult=>doSomeThingThird(newResult,finalResult=>console.log(finalResult),errCallback),errCallback),errCallback)//promise嵌套doSomeThing 查看详情
[js]回调函数和回调地狱(代码片段)
...在JavaScript中可以作为参数或作为返回值,在异步编程中回调函数被大量使用,当回调函数被调用,说明满足了某个触发条件,有时还会包含结果,提供更多的细节。回调函数可能会出现回调地狱现象,可以利用Promise对象解决该... 查看详情
c语言函数指针做函数参数(即回调函数)(代码片段)
文章目录函数指针做函数参数(回调函数)回调函数概念一般有三种调用方式回调函数的作用回调函数调用时刻回调函数的语法:1.简单的函数类型为:无参数、无返回值的函数。2.完全形式的回调函数注:代码案例... 查看详情
c语言函数指针做函数参数(即回调函数)(代码片段)
文章目录函数指针做函数参数(回调函数)回调函数概念一般有三种调用方式回调函数的作用回调函数调用时刻回调函数的语法:1.简单的函数类型为:无参数、无返回值的函数。2.完全形式的回调函数注:代码案例... 查看详情
进程池中的回调函数(代码片段)
#回调函数#指定一个任务后、并且指定一个回调函数后,当指定的进程池执行的任务结束后,会将该任务的返回值作为回调函数的参数传递到回调函数中,并且回调函数得以执行#回调函数在主进程中被执行#importos#frommultiprocessingi... 查看详情
对回调函数的理解(代码片段)
...t,IDisposable234[SecuritySafeCritical]5publicTimer(TimerCallbackcallback);6回调函数就是在函数的参数列表中传入一个函数,例如在C#中通过委托传入一个函数,然后在函数体内部执行传入的函数 --------------------20 查看详情
js回调函数(代码片段)
js回调函数 回调函数(没有调用也会执行)就是一个参数,把这个参数传到另一个函数里面,也就是主函数里面,当主函数里面的事情干完再回头去执行当做参数传进去的回调函数,回头去调用,这... 查看详情