(c + +) Callback Function

Source: Internet
Author: User
Tags call back what callback

Original: http://www.codeguru.com/cpp/cpp/cpp_mfc/callbacks/article.php/c10557/Callback-Functions-Tutorial.htm

Callback Functions tutorialintroduction

If You is reading this article, you probably wonder what callback functions is. This article explains what callback functions is, what is they good for, why do you should use them, and so forth. However, before learning what callback functions is, you must is familiar with function pointers. If you aren ' t, consult A/C + + book or consider reading the following:

    • The Syntax of C and C + + Function pointers
    • Pointers to member functions
    • declaring, assigning, and Using Function pointers
(Note: The key is to understand the function pointer)What is a Callback Function?

The simple answer to this first question is, a callback function is a function which is called through a function p Ointer. If you pass the pointer (address) of a function as an argument to another, when that pointer are used to the function It points to it is said, a call back is made.

(Note: A callback function is a function called through a "function pointer") Why should do I use Callback Functions?

Because They uncouple the caller from the callee. The caller doesn ' t care who the callee is; All it knows are that there are a callee with a certain prototype and probably some restriction (for instance, the returned Value can is int, but certain values has certain meanings).

If you were wondering how was that useful in practice, imagine the want to the write a library that provides implementation For sorting algorithms (yes, that's pretty classic), such as bubble sort, shell short, shake sort, quick sort, and other S. The catch is so you don ' t want to embed the sorting logic (which of the elements goes first in a array) into your FU Nctions, making your library more general to use. You want the client to being responsible to that kind of logic. Or, you want it to is used for various data types (ints, floats, strings, and so on). So, how does it? you use the function pointers and make callbacks.

(Note: To invoke an external function to implement some functions, but this external function can return to call this function to implement some of the logic, to achieve customization.) )

A callback can is used for notifications. For instance, you need to set a timer in your application. Each time the timer expires, your application must is notified. But, the implementer of the time ' RS mechanism doesn ' t know anything about your application. It is wants a pointer to a function with a given prototype, and the using that pointer it makes a callback, notifying R application about the event it has occurred. Indeed, the SetTimer () WinAPI uses a callback function to notify that the timer have expired (and, in case there are no call Back function provided, it posts a message to the application ' s queue).

Another example from WinAPI functions It use callback mechanism are Enumwindow (), which enumerates all the top-level wind OWS on the screen. Enumwindow () Iterates over the top-level windows, calling a application-provided function for each window, passing the HA Ndler of the window. If The callee returns a value, the iteration continues; Otherwise, it stops. EnumWindows () just doesn ' t care where the callee are and what it does with the handler it passes over. It is only interested in the return value, because based on that it continues its execution or not.

However, callback functions is inherited from C. Thus, in C + +, they should is only used for interfacing C code and existing callback interfaces. Except for these situations, you should use virtual methods or functors, not callback functions.

A Simple Implementation Example

Now, follow the example so can be found in the attached files. I have created a dynamic linked library called Sort.dll. It exports a type called Comparefunction:

typedef int (__stdcall *comparefunction) (const byte*, const byte*);

Which'll be the type of your callback functions. It also exports-methods, called Bubblesort () and Quicksort (), which has the same prototype but provide different Beha Vior by implementing the sorting algorithms with the same name.

void Dlldir __stdcall Bubblesort (byte* array,                                 int size,                                 int elem_size,                                 comparefunction cmpfunc); void Dlldir __stdcall Quicksort (byte* array,                                int size,                                int elem_size,                                comparefunction cmpfunc);

These functions take the following parameters:

    • byte* Array: A pointer to an array of elements (doesn ' t matter of which type)
    • int size: The number of elements in the array
    • int elem_size: The size, in bytes, and of an element of the array
    • comparefunction cmpfunc: A pointer to a callback function with the prototype listed above

The implementation of these, functions performs a sorting of the array. But, each time there was a need to decide which of the elements goes first, a callback was made to the function whose addres S is passed as an argument. For the library writer, it doesn ' t matter where this function is implemented, or what it is implemented. All that matters it was that it takes the address of both elements (that's the the both be compared) and it returns one of the Following values (this was a contract between the library developers and its clients):

    • -1:if the first element is lesser and/or should go before the second element (in a sorted array)
    • 0:if the elements is equal and/or their relative position doesn ' t matter (each one can go before the other in a sort Ed Array)
    • 1:if the first element is greater and/or should go after the second element (in a sorted array)

With this contract explicitly stated, the implementation of the Bubblesort () function are this (for Quicksort (), which a Li Ttle bit more complicated, see the attached files).

 void Dlldir __stdcall Bubblesort (byte* array, int size, int elem_size, comparefunction cmpfunc) {for (Int. i=0; i < size; i++) {for ( int j=0; J < Size-1;                  J + +) {//Make the callback to the comparison function if (1 = = (*cmpfunc) (Array+j*elem_size, array+ (j+1) *elem_size) {//The compared elements must be interchanged byte* t            EMP = new Byte[elem_size];            memcpy (temp, array+j*elem_size, elem_size);            memcpy (Array+j*elem_size, array+ (j+1) *elem_size, elem_size);            memcpy (array+ (j+1) *elem_size, temp, elem_size);         delete [] temp; }      }   }}
Note: Because The implementation uses memcpy (), these library functions should not being used for types other th An POD (Plain-old-data).

On the client side, there must are a callback function whose address is to being passed to the Bubblesort () function. As a simple example, I has written a function that compares II integer values and one that compares II strings:

int __stdcall compareints (const byte* velem1, const byte* velem2) {   int elem1 = * (int*) velem1;   int elem2 = * (int*) velem2;   if (Elem1 < elem2)      return-1;   if (Elem1 > Elem2)      return 1;   return 0;} int __stdcall comparestrings (const byte* velem1, const byte* VELEM2) {   const char* elem1 = (char*) velem1;   Const char* ELEM2 = (char*) velem2;   Return strcmp (Elem1, elem2);}

To put the these to a test, I has written this short program. It passes an array with five elements to Bubblesort () or Quicksort () along with the pointer to the callback functions.

 int main (int argc, char* argv[]) {int i;   int array[] = {5432, 4321, 3210, 2109, 1098};   cout << "before sorting ints with bubblesort\n";   for (i=0; i < 5; i++) cout << array[i] << ' \ n ';   Bubblesort ((byte*) array, 5, sizeof (Array[0]), &compareints);   cout << "after the sorting\n";   for (i=0; i < 5; i++) cout << array[i] << ' \ n ';                            const char STR[5][10] = {"Estella", "Danielle", "Crissy",   "Bo", "Angie"};   cout << "before sorting strings with quicksort\n";   for (i=0; i < 5; i++) cout << str[i] << ' \ n ';   Quicksort ((byte*) str, 5, ten, &comparestrings);   cout << "after the sorting\n";   for (i=0; i < 5; i++) cout << str[i] << ' \ n '; return 0;} 

If I decide that I want the sorting-to-be-done descending (with the biggest element first), and all I had to-do are to change The callback function code, or provide another that implements the desired logic.

Calling conventions

In the above code, you can see the word  __stdcall  in The function ' s prototype. Because It starts with a double underscore, it's, of course, a compiler-specific extension, more exactly a microsoft-spec Ific one. Any compiler the supports development of win32-based applications must support this or an equivalent one. A function is marked with , __stdcall  uses the standard calling convention so named because all Win3 2 API functions (except the few that take variable arguments) use it. Functions that follow the standard calling convention remove the parameters from the stack before they return to the Calle R. The standard convention for Pascal. But in C + +, the calling convention is and the caller cleans up the stack instead of the called function. To enforce that a function uses the C + + calling convention,  __cdecl  must be used. Variable argument functions use the C + + calling convention.

Windows adopted the standard calling convention (Pascal Convention) because it reduces the size of the code. This is very important in the early days of Windows, when it ran on systems with 640 KB RAM.

If you don't like the word __stdcall, you can use the CALLBACK macro, defined in Windef.h, as

#define CALLBACK    __stdcall

Or

#define CALLBACK    PASCAL

Where PASCAL is #defined as __stdcall.

You can read more about calling convention here:calling Convetions in Microsoft Visual C + +.

C + + Methods as Callback Functions

Because probably write in C + +, you want your callback function a method of a class. But, if you try this:

Class Ccallbacktester{public:   int CALLBACK compareints (const byte* velem1, const byte* velem2);}; Bubblesort ((byte*) array, 5, sizeof (Array[0]),           &ccallbacktester::compareints);

With a MS compiler, you get this compilation error:

Error C2664: ' Bubblesort ': cannot convert parameter 4 from ' Int (__stdcall ccallbacktester::*) (const unsigned char *,cons T unsigned char *) ' to ' int (__stdcall *) (const unsigned char *,const unsigned char *) ' There are no context in which this Conversion is possible

That happens because Non-static member functions has an additional parameter, pointer This (see this FAQ for mor e).

That obliges the member function static. If that's not a acceptable, you can use the several techniques to overcome. Check The following links to learn more.

    • How to Implement callbacks in C and C + +
    • C + + Callback Demo
    • Callbacks in C + + Using Template Functors
Notices

The attached files contain the projects. Sortingdll is a Win32 DLL project. The Sort.dll output library exports the sorting functions, Bubblesort () and Quicksort (). The second project, Sortdemo, is a Win32 Console application this demonstrates how to use the Sort.dll library. The output directory for both projects are Shared directory, where the following files can be found:sort.h, sort. DLL, Sort.lib, and SortDemo.exe.

Further References
    • C + + OO Callback technique
    • Function pointers to Non-static Object Methods
    • Pointers and References

(c + +) Callback Function

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.