一、什么是回调函数
软件模块之间总是存在着一定的接口,回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。回调函数是通过函数指针调用的函数。把函数的指针(地址)作为参数传递给另一个函数,当这个指针调用其所指向的函数时,就称这是回调函数。回调函数不是实现该函数的软件模块直接调用,而是在特定的事件或条件发生时由另外的软件模块通过函数指针的方式调用,用于对该事件或条件进行响应,是一种下层软件模块调用上层软件模块的特殊方式。
回调函数就是可以进行参数传递的函数。这种函数在C语言、c++和一些其他的编程语言中有着十分重要的作用。回调函数的工作原理就是在特定的条件下,使用函数指针的一方将这种函数回调给提供函数的一方,从而实现对事件的回调处理。简单来说,这种函数就是运用函数指针将数值或程序做返回处理的一种函数。
二、回调函数的作用
这种函数的巨大作用解耦合,不用管被调用者,仅仅需要的是原函数以及一定的限制条件。主程序将回调函数作为参数传递给库函数,只要改变传递给库函数的参数,就可以实现不同的功能,不需要改变库函数的功能。库函数和主程序一般不属于一层或者一个模块,库函数是按照通用性设计的,不知道主程序会用什么样的函数处理;也就是说不能通过修改库函数调用普通函数的方式实现,那就需要通过参数传入不同的回调函数。
这样就会便于这个函数可以采用更加灵活的方法去处理相似的情况。
三、分析实现Lab5.2中的代码
linkable.c文件中定义SearchLinkTableNode函数作为Call-in函数接口。其中的Condition函数为Callback函数,作为参数传入。
/*
* Serach a LinkTableNode from LinkTable
* int Condition(tLinkTableNode *pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable,
int Condition(tLinkTableNode *pNode, void *args),
void * args)
{
if (pLinkTable == NULL || Condition == NULL)
{
return NULL;
}
tLinkTableNode * pNode = pLinkTable->pHead;
while (pNode != NULL)
{
if (Condition(pNode, args) == SUCCESS)
{
return pNode;
}
pNode = pNode->pNext;
}
return NULL;
}
可以看到代码中没有Condition函数的代码实现,因为Condition是用户代码传进来的一个函数指针,只是我们在回调函数接口定义时规定了传进来的函数指针的规格。
menu.c中具体定义了Condition传递的参数,即SearchConditon函数,再传递到FindCmd函数中
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
int main()
{
InitMenuData(&head);
/* cmd line begins */
while (1)
{
char cmd[CMD_MAX_LEN];
printf("Input cmd > ");
scanf("%s", cmd);
tDataNode *p = FindCmd(head, cmd);
if (p == NULL)
{
printf("This is a wrong cmd!\n");
continue;
}
printf("%s - %s\n", p->cmd, p->desc);
if (p->handler != NULL)
{
p->handler();
}
}
return 0;
}
作者:090