在Learning OpenCV
书中,我提到了callback
,有时与routine
一起称为callback routine
。
我们说的callback
是什么意思?
谢谢。
什么是Callback函数?
简单来说,回调函数是程序员不显式调用的函数。相反,有一些机制可以持续等待事件的发生,并且它将调用选定的函数来响应特定的事件。当一个操作(函数)需要很长时间才能执行,而函数的调用者不想等到操作完成,但确实希望知道操作的结果时,通常使用这种机制。通常,回调函数帮助实现这样的异步机制,其中调用方注册以获得有关耗时处理和连续其他操作的结果的动画,而在稍后的时间点,调用方获得结果的通知。
一个实际的例子:
Windows事件处理:
实际上所有的Windows程序都设置了一个事件循环,这使得程序通过调用函数来响应特定的事件(例如按钮按下,选择一个复选框,窗口获得焦点)。方便的事情是,程序员可以指定当(比如说)按下特定按钮时调用什么函数,即使不可能指定何时按下按钮。被调用的函数被称为回调函数。
源代码说明:
//warning: Mind compiled code, intended to illustrate the mechanism
#include <map>
typedef void (*Callback)();
std::map<int, Callback> callback_map;
void RegisterCallback(int event, Callback function)
{
callback_map[event] = function;
}
bool finished = false;
int GetNextEvent()
{
static int i = 0;
++i;
if (i == 5) finished = false;
}
void EventProcessor()
{
int event;
while (!finished)
{
event = GetNextEvent();
std::map<int, Callback>::const_iterator it = callback_map.find(event);
if (it != callback_map.end()) // if a callback is registered for event
{
Callback function = *it;
if (function)
{
(*function)();
}
else
{
std::cout << "No callback foundn";
}
}
}
}
void Cat()
{
std::cout << "Catn";
}
void Dog()
{
std::cout << "Dogn";
}
void Bird()
{
std::cout << "Birdn";
}
int main()
{
RegisterCallBack(1, Cat);
RegisterCallback(2, Dog);
RegisterCallback(3, Cat);
RegisterCallback(4, Bird);
RegisterCallback(5, Cat);
EventProcessor();
return 0;
}
上面的命令将输出如下内容:
Cat
Dog
Cat
Bird
Cat
希望这对你有帮助!
注意:
从我的一个旧答案中导入这个答案。
"我自己不调用它,但系统(或其他一些人)会调用它"。这是调。
它们意味着您将指向过程的指针传递给OpenCV
。当事情发生时,这将是called back
。这可以在cvSetMouseCallback()
中看到。当鼠标移动时,指针所引用的函数将被调用。
遵循好莱坞的原则"不要呼叫我们,我们呼叫你",回调是对传递给另一个函数的函数的引用。
当数据可用或需要执行某些处理步骤时,回调函数将调用它。
此处的"Routine"与"function"相同。这个术语可以追溯到较早的语言(如Fortran),它们在返回值的函数和不返回值的(子)例程之间做出了区别。
"回调"是一种技术,当你向系统/API/框架提供一个指向你的函数("例程")的指针时,系统/API/框架会在它想这样做的时候回调它。因此,回调例程,或简称回调,就是用于这种用途的函数。
在严格的对象语言(如Java)中,它们通常使用侦听器和委托。c++形式的回调技术有一个优点,那就是它与非面向对象的语言(如经典C语言)兼容。
EDIT:在Microsoft C运行时库中,这种技术用于qsort()函数。compare
参数是指向回调例程的函数指针。每当两个数组元素需要比较时,RTL就会调用它。这不是一个典型的例子,因为所有对compare
的调用都发生在qsort()调用返回之前。
在Win32 API中,回调是主要的。窗口过程就是一个典型的例子——你在WNDCLASS结构中传递一个指向它的指针,当消息到达时,系统会回调这个过程。在这种情况下,回调例程在RegisterClass()之后很久才被调用——在窗口的整个生命周期中。
在POSIX/Unix/Linux中,以信号处理函数为例。参见signal()系统调用描述
回调函数是不显式调用的函数,此类函数在某些事件发生后自动调用,例如按下"ctrl+c"后产生SIGINT信号,因此自动处理程序将执行