C中的函数调用者(回调)?

3 c function

所以我想知道它们是如何工作的.为了解释我的意思是"函数调用者" glutTimerFunc,这是我的意思的一个很好的例子,它能够接受一个函数作为参数并调用它,即使它不知道它被声明.它是怎么做到的?

Fir*_*aad 6

你所说的叫做回调,用C和C++中的函数指针实现.

既然你提到了过剩,那么让我们直接从freeglut源代码中获取一个真实的例子.我将使用glutIdleFunc而不是glutTimerFunc,因为代码更简单.

在glut中,idle函数回调(你提供给glutIdleFunc的是)一个指向函数的指针,该函数不带任何参数并且什么都不返回.typedef用于为这样的函数类型命名:

typedef void (* FGCBIdle)( void );
Run Code Online (Sandbox Code Playgroud)

这里,FGCBIdle(FreeGlut CallBack Idle的缩写)被定义为指向不带参数且返回类型为void的函数的指针.这只是一种类型定义,使编写表达式更容易,它不分配任何存储.

Freeglut有一个名为SFG_State的结构,它包含各种设置.该结构的部分定义是:

struct tagSFG_State
{
    /* stuff */
    FGCBIdle         IdleCallback;         /* The global idle callback       */
    /* stuff */
};
Run Code Online (Sandbox Code Playgroud)

该结构包含一个FGCBIdle类型的变量,我们建立的是特定函数指针的另一个名称.您可以将IdleCallback字段设置为指向用户使用glutIdleFunc函数提供的函数的地址.该函数的(简化)定义是:

void glutIdleFunc( void (* callback)( void ) )
{
    fgState.IdleCallback = callback;
}
Run Code Online (Sandbox Code Playgroud)

这里,fgState是一个SFG_State变量.如您所见,glutIdleFunc接受一个参数,该参数是一个函数指针,该函数指向不带参数且不返回任何内容的函数,此参数的名称为回调函数.在函数内部,全局fgState变量中的IdleCallback设置为用户提供的回调.当你调用glutIdleFunc函数时,你传递了你自己的函数的名字(例如glutIdleFunc(myIdle)),但你真正传递的是函数的地址.

之后,在glutMainLoop发起的大过量事件处理循环中,您将找到以下代码:

if( fgState.IdleCallback )
{
            /* stuff */
            fgState.IdleCallback( );
}
Run Code Online (Sandbox Code Playgroud)

如果用户提供的空闲回调可用,则在循环中调用它.如果您在我的帖子开头检查函数指针教程,您将更好地理解语法,但我希望现在的一般概念更有意义.