Function calls (callbacks) in C?

So I was wondering how they work. To explain what I mean by “calling the function”, a good example of what I mean is glutTimerFunc , it can take a function as a parameter and even call it with it, not knowing what it is declared. How it's done?

+3
source share
3 answers

What you're talking about is called callback and implemented using function pointers in C and C ++.

Since you mentioned overflow, let's take a real example directly from the freeglut source code. I will use glutIdleFunc instead of glutTimerFunc, because the code is simpler.

In oversaturation mode, the function callback function (that you supply glutIdleFunc) is a pointer to a function that takes no parameters and returns nothing. The typedef type is used to give this type of function a name:

 typedef void (* FGCBIdle)( void ); 

Here, FGCBIdle (short for FreeGlut CallBack Idle) is defined as a pointer to a function that takes no parameters and whose return type is invalid. This is just a type definition that makes it easy to write an expression; it does not allocate any storage.

Freeglut has an SFG_State structure that contains various settings. Part of the definition of this structure:

 struct tagSFG_State { /* stuff */ FGCBIdle IdleCallback; /* The global idle callback */ /* stuff */ }; 

The structure contains a variable of type FGCBIdle, which we set, is a different name for a specific function pointer. You can set the IdleCallback field to indicate the address of the function that the user provides with the glutIdleFunc function. A simplified definition of this function:

 void glutIdleFunc( void (* callback)( void ) ) { fgState.IdleCallback = callback; } 

Here fgState is an SFG_State variable. As you can see, glutIdleFunc takes one parameter, which is a pointer to a function that takes no parameters and returns nothing, this parameter name is a callback. Inside the IdleCallback function inside the global variable fgState is set to a callback provided by the user. When you call the glutIdleFunc function, you pass the name of your own function (e.g. glutIdleFunc (myIdle)), but what you really pass is the address of the function.

Later, inside the glutMainLoop-initiated large attenuation processing loop, you will find this code:

 if( fgState.IdleCallback ) { /* stuff */ fgState.IdleCallback( ); } 

If the user has provided an idle callback, it is called in a loop. If you check out the function pointer lesson at the beginning of my post, you’ll better understand the syntax, but I hope the general concept makes more sense.

+6
source

A parameter is a pointer to a function. The responsibility of the caller is that the function declaration meets the requirements (for example, the number and type of parameters, the calling agreement).

+2
source

A function passed as a parameter is passed as a function pointer.

In compiled code, a function is nothing more than an address that the CPU can carry for execution. When you pass a pointer to a function, the compiler (and later the linker) inserts the correct address into the call.

Functional parameters should correspond in the same way that the executable code simply pushes the values ​​on the stack (or registers depending on the architecture) and expects to display (read) the return value.

0
source

Source: https://habr.com/ru/post/1312611/


All Articles