工程化编程实战callback接口学习笔记
1、在VSCode下编译运行lab5-1.tar.gz 即http://pan.baidu.com/s/1pJ0qAIv
2、通过VSCode+GDB调试程序找出quit命令无法运行的bug产生的原因
3、分析callback接口的运行机制,总结callback接口设计的方法
一、环境准备
第一次运行时使用windows平台运行程序,发现缺少pthread.h,Linux系统下的多线程遵循POSIX线程接口,称为pthread,为了方便后续实验,决定更换linux平台。当然,也可以选择下载windows上的pthread插件[1]。
linux中使用sudo apt-get install gcc指令配置gcc环境,并安装上gdb用来调试代码。
sudo apt-get install gcc sudo apt-get install gdb
vscode中安装下列插件。
其中code runner是一款运行代码较为方便的插件,可以替你输入的运行指令。
二、运行代码
1、编译文件
下载代码结构如下所示,本程序是通过menu这个主程序实现各项链表的功能。
menu.c引用linktable.h这个头文件后,在编译时需要将该头文件对应的源文件进行连接再编译,否则会出现找不到对应函数的报错。
由于需要使用gdb进行调试,因此需要加上参数[2]。
gcc -g menu.c linktable.c -o menu
2、运行程序
gdb ./menu
(gdb)help
(gdb)version
(gdb)quit
此处发现,提醒为错误指令,找到对应代码发现是由于p为空指针引起的,因此在对应的行数设置断点。
gdb设置断点。
(gdb)b FindCmd
(gdb) ls
(gdb) b SearchCondition
查看上下文,发现是SearchLinkTableNode函数及回调函数SearchCondition。
(gdb) b SearchLinkTableNode
追溯到头文件的SearchLinkTableNode函数,该函数的作用是找到满足condition的节点,将Condition作为判断条件。
结合上面位于menu.c的Condition函数,本程序中实现了找到与输入cmd字符串对应的那个链表节点。
2、修改并运行程序
由检测到的位置判断是由于节点数的问题,quit指令对应的节点位于链表的结尾,该循环无法检测到最后一个节点,尝试将149行代码修改成。
while(pNode != NULL)
重新运行程序,发现跳转到Quit处理程序,直接退出程序。
二、回调函数的使用
1、callback机制介绍
这⾥SearchLinkTableNode函数派遣了⼀个Conditon作为callback函数,收集的情报范围tLinkTableNode * pNode,⼀旦发现⽬标情报卧底就被激活return pNode。利⽤callback函数参数能够使Linktable的查询接⼝更加通⽤。
callback函数是异步执行的,当回调函数在执行时,主体也在执行。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。使用回调函数的一个优点就是实现了调用者与被调用者分离,调用者不必关心被调用者具体如何实现,它只要明确自己的需求即可,这个需求是由被调用者来满足的。
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode)) { if(pLinkTable == NULL || Conditon == NULL) { return NULL; } tLinkTableNode * pNode = pLinkTable->pHead; while(pNode != NULL) { if(Conditon(pNode) == SUCCESS) { return pNode; } pNode = pNode->pNext; } return NULL; } int SearchCondition(tLinkTableNode * pLinkTableNode) { tDataNode * pNode = (tDataNode *)pLinkTableNode; if(strcmp(pNode->cmd, cmd) == 0) { return SUCCESS; } return FAILURE; }
2、callback接口设计的方法
callback接口需要将原型函数设计好,必须考虑到空指针等各种不利因素,需要添加各种条件让原型函数更加具有通用性。使用回调函数接口时,可以在自己的程序内设定好限制因素,再在回调函数中使用函数指针调用该因素,回调函数使得接口具有高度的可重用性。
参考:
[1] https://www.cnblogs.com/lzpong/p/6145511.html
[2]https://blog.csdn.net/mercy_ps/article/details/81542986 GDB调试基本命令