回调函数 ╰+攻爆jí腚メ 2022-06-16 23:37 292阅读 0赞 一、回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理、用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函数)有何不同呢? 使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。 而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的 API函数有关,一般在帮助中有说明回调函数的参数和返回值等。C++中一般要求在回调函数前加CALLBACK(相当于FAR PASCAL),这主要是说明该函数的调用方式。 至于钩子函数,只是回调函数的一个特例。习惯上把与SetWindowsHookEx函数一起使用的回调函数称为钩子函数。也有人把利用VirtualQueryEx安装的函数称为钩子函数,不过这种叫法不太流行。 也可以这样,更容易理解:回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事: 1. 声明; 2. 定义; 3. 设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用。 声明和定义时应注意:回调函数可以作为类的成员函数,但必须声明为静态方法。 二、回调函数、消息和事件例程 调用(calling)机制从汇编时代起已经大量使用:准备一段现成的代码,调用者可以随时跳转至此段代码的起始地址,执行完后再返回跳转时的后续地址。 CPU为此准备了现成的调用指令,调用时可以压栈保护现场,调用结束后从堆栈中弹出现场地址,以便自动返回。借堆栈保护现场真是一项绝妙的发明,它使调用 者和被调者可以互不相识,于是才有了后来的函数和构件。 此调用机制并非完美。回调函数就是一例。函数之类本是为调用者准备的美餐,其烹制者应对食客了如指掌,但实情并非如此。例如,写一个快速排序函数供他人调 用,其中必包含比较大小。麻烦来了:此时并不知要比较的是何类数据--整数、浮点数、字符串?于是只好为每类数据制作一个不同的排序函数。更通行的办法是 在函数参数中列一个回调函数地址,并通知调用者:君需自己准备一个比较函数,其中包含两个指针类参数,函数要比较此二指针所指数据之大小,并由函数返回值 说明比较结果。排序函数借此调用者提供的函数来比较大小,借指针传递参数,可以全然不管所比较的数据类型。被调用者回头调用调用者的函数(够咬嘴的),故 称其为回调(callback)。 回调函数使程序结构乱了许多。Windows API 函数集中有不少回调函数,尽管有详尽说明,仍使初学者一头雾水。恐怕这也是无奈之举。 无论何种事物,能以树形结构单向描述毕竟让人舒服些。如果某家族中孙辈又是某祖辈的祖辈,恐怕无人能理清其中的头绪。但数据处理之复杂往往需要构成网状结构,非简单的客户/服务器关系能穷尽。 Windows 系统还包含着另一种更为广泛的回调机制,即消息机制。消息本是 Windows 的基本控制手段,乍看与函数调用无关,其实是一种变相的函数调用。发送消息的目的是通知收方运行一段预先准备好的代码,相当于调用一个函数。消息所附带的 WParam 和 LParam 相当于函数的参数,只不过比普通参数更通用一些。应用程序可以主动发送消息,更多情况下是坐等 Windows 发送消息。一旦消息进入所属消息队列,便检感兴趣的那些,跳转去执行相应的消息处理代码。操作系统本是为应用程序服务,由应用程序来调用。而应用程序一旦 启动,却要反过来等待操作系统的调用。这分明也是一种回调,或者说是一种广义回调。其实,应用程序之间也可以形成这种回调。假如进程 B 收到进程 A 发来的消息,启动了一段代码,其中又向进程 A 发送消息,这就形成了回调。这种回调比较隐蔽,弄不好会搞成递归调用,若缺少终止条件,将会循环不已,直至把程序搞垮。若是故意编写成此递归调用,并设好 终止条件,倒是很有意思。但这种程序结构太隐蔽,除非十分必要,还是不用为好。 利用消息也可以构成狭义回调。上面所举排序函数一例,可以把回调函数地址换成窗口 handle。如此,当需要比较数据大小时,不是去调用回调函数,而是借 API 函数 SendMessage 向指定窗口发送消息。收到消息方负责比较数据大小,把比较结果通过消息本身的返回值传给消息发送方。所实现的功能与回调函数并无不同。当然,此例中改为消 息纯属画蛇添脚,反倒把程序搞得很慢。但其他情况下并非总是如此,特别是需要异步调用时,发送消息是一种不错的选择。假如回调函数中包含文件处理之类的低 速处理,调用方等不得,需要把同步调用改为异步调用,去启动一个单独的线程,然后马上执行后续代码,其余的事让线程慢慢去做。一个替代办法是借 API 函数 PostMessage 发送一个异步消息,然后立即执行后续代码。这要比自己搞个线程省事许多,而且更安全。 如今我们是活在一个 object 时代。只要与编程有关,无论何事都离不开 object。但 object 并未消除回调,反而把它发扬光大,弄得到处都是,只不过大都以事件(event)的身份出现,镶嵌在某个结构之中,显得更正统,更容易被人接受。应用程序 要使用某个构件,总要先弄清构件的属性、方法和事件,然后给构件属性赋值,在适当的时候调用适当的构件方法,还要给事件编写处理例程,以备构件代码来调 用。何谓事件?它不过是一个指向事件例程的地址,与回调函数地址没什么区别。 不过,此种回调方式比传统回调函数要高明许多。首先,它把让人不太舒服的回调函数变成一种自然而然的处理例程,使编程者顿觉气顺。再者,地址是一个危险的 东西,用好了可使程序加速,用不好处处是陷阱,程序随时都会崩溃。现代编程方式总是想法把地址隐藏起来(隐藏比较彻底的如 VB 和 Java),其代价是降低了程序效率。事件例程(?)使编程者无需直接操作地址,但并不会使程序减速。 (例程似乎是进程的台湾翻译。) 三、精妙比喻:回调函数还真有点像您随身带的BP机:告诉别人号码,在它有事情时Call您。 回调用于层间协作,上层将本层函数安装在下层,这个函数就是回调,而下层在一定条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了 完成本层的处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据通信中很普遍。其实回调和API非常接近,他们的共性都是 跨层调用的函数。但区别是API是低层提供给高层的调用,一般这个函数对高层都是已知的;而回调正好相反,他是高层提供给底层的调用,对于低层他是未知 的,必须由高层进行安装,这个安装函数其实就是一个低层提供的API,安装后低层不知道这个回调的名字,但它通过一个函数指针来保存这个回调,在需要调用 时,只需引用这个函数指针和相关的参数指针。 其实:回调就是该函数写在高层,低层通过一个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调用高层那个函数。 四、调用方式 [http://blog.csdn.net/fazai001/article/details/6767236][http_blog.csdn.net_fazai001_article_details_6767236] [http_blog.csdn.net_fazai001_article_details_6767236]: http://blog.csdn.net/fazai001/article/details/6767236
相关 回调函数 作者:桥头堡 链接:http://www.zhihu.com/question/19801131/answer/27459821 来源:知乎 著作权归作者所有,转载 清疚/ 2022年09月24日 11:26/ 0 赞/ 34 阅读
相关 回调函数 一、回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理、用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义 ╰+攻爆jí腚メ/ 2022年06月16日 23:37/ 0 赞/ 293 阅读
相关 回调函数 回调函数是一种函数指针的使用方式。 stdcall和cdecl的区别:这个问题涉及到函数调用的汇编知识,暂只需记住stdcall和cdecl的参数压栈顺序是相同的,参 傷城~/ 2022年06月12日 07:21/ 0 赞/ 303 阅读
相关 回调函数 作者:no.body 链接:https://www.zhihu.com/question/19801131/answer/27459821 来源:知乎 著作权归作者 ╰半夏微凉°/ 2022年06月11日 05:37/ 0 赞/ 58 阅读
相关 回调函数 转自: 回调函数 在看LWIP时,见到用回调函数,再看某老外公司OPC源代码时,见到用回调函数。看我国内某些代码( 朴灿烈づ我的快乐病毒、/ 2022年06月11日 05:36/ 0 赞/ 270 阅读
相关 回调函数 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实 青旅半醒/ 2022年06月02日 20:51/ 0 赞/ 306 阅读
相关 回调函数 转载自[https://zhidao.baidu.com/question/572699725.html][https_zhidao.baidu.com_question_57 水深无声/ 2021年12月12日 04:01/ 0 赞/ 481 阅读
相关 回调函数 作为JS的核心,回调函数和异步执行是紧密相关的,也是必须跨过去的一道个门槛。 那么究竟什么是回调函数(Callback),其实回调函数并不复杂,明白两个重点即可: 1. 函 桃扇骨/ 2021年11月13日 21:28/ 0 赞/ 534 阅读
相关 回调函数 一、定义 什么是回调函数?它首先是一个函数,这是肯定的,我举个例子:有两个函数A和B,首先应用程序将A的地址告诉B,这称之为注册回调函数,B在收到外部某个命令的时候,可以根据 客官°小女子只卖身不卖艺/ 2021年09月30日 11:56/ 0 赞/ 573 阅读
相关 回调与回调函数 回调与回调函数 回调 回调函数 回调 回调指的是某函数在执行的时候,由于某些原因,该函数被迫中止执行,交出当前线程的使用权,当前线程转而执行其它函 悠悠/ 2021年09月25日 04:26/ 0 赞/ 565 阅读
还没有评论,来说两句吧...