1.什么是回调函数
一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数。
2.结合源码分析CallBack函数
linktableInternal.h:实现了链表基本节点结构,LinkTable封装了链表头,链表尾,以及链表长度:
struct LinkTableNode
{
struct LinkTableNode * pNext;
};
struct LinkTable
{
struct LinkTableNode *pHead;
struct LinkTableNode *pTail;
int SumOfNode;
pthread_mutex_t mutex;
};
linktable.h:基于此链表结构,实现了创建链表,删除链表,添加和删除链表节点。在这一层定义了call-in、callback函数的接口。
tLinkTable * CreateLinkTable();
int DeleteLinkTable(tLinkTable *pLinkTable);
int AddLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode);
int DelLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode);
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode);
menu.c:实现了多态,基于LinkTableNode实现了真正的功能节点,并定义了执行指定功能的回调函数:
/* find a cmd in the linklist and return the datanode pointer */
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)cmd);
}
typedef struct DataNode
{
tLinkTableNode head;
char* cmd;
char* desc;
int (*handler)();
} tDataNode;
Callback函数需要一个Call-in函数,在这个例子里的接口定义如下
/*
* Search a LinkTableNode from LinkTable
* int Conditon(tLinkTableNode * pNode, void * args);
*/
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
此函数接收一个回调(CallBack函数)Condition。
在menu.c中具体定义了查询条件
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
FindCmd调用SearchCondition,要把自己的参数传给后者,可以选择①不给SearchLinkTableNode及其接口Condition加参数,声明一个全局变量,随用随赋值;②增加参数,在FindCmd函数体里把cmd链表指针传给SearchLinkTableNode。
这样实现多态这样可以有效地隐藏软件模块内部的实现细节,降低了代码之间的耦合度。