What Is a Web Callback?
A callback function is a function called through a function pointer. If you pass a function pointer (address) as an argument to another function, when this pointer is used to call the function it points to, we say that this is a callback function. The callback function is not directly called by the implementor of the function, but is called by another party when a specific event or condition occurs, and is used to respond to the event or condition.
Callback
- Define a callback function;
- The party that provided the function implementation will call back the function when it is initialized
- Because the caller can be separated from the callee, the caller does not care who is the callee. It only needs to know that there exists a specific prototype and constraints
Callback function code implementation
- The following creates a dynamic link library of sort.dll, which exports a type named CompareFunction-
typedef int (__ stdcall * CompareFunction) (constbyte *, constbyte *)
- It is the type of callback function, which is responsible for passing parameters to the corresponding specific element comparison function with the same parameter form. In addition, through it, two different sorting algorithms can call comparison functions related to specific elements to achieve sorting independent of element type: Bubblesort () and Quicksort (). Both methods use the same parameter prototype, but Implemented different sorting algorithms.
void DLLDIR__stdcallBubblesort (byte * array, int size, int elem_size, CompareFunction cmpFunc); void DLLDIR__stdcallQuicksort (byte * array, int size, int elem_size, CompareFunction cmpFunc);
- These two functions accept the following parameters:
- Byte * array: pointer to an array of elements (any type).
- · Int size: the number of elements in the array.
- Int elem_size: the size of an element in the array, in bytes.
- · CompareFunction cmpFunc: A pointer to a callback function with the above prototype.
- These two functions will sort the array somehow, but each time you need to decide which two elements come first, and there is a callback function in the function whose address is passed in as a parameter. For the writer, you don't need to care where the function is implemented or how it is implemented. All you need to care about is the address of the two elements for comparison and return one of the following values (the library writer and use Both must abide by this convention):
- · -1: If the first element is smaller, it should be in the sorted array and should be before the second element.
- 0: If two elements are equal, their relative position is not important. In the sorted array, it doesn't matter who is in front.
- · 1: If the first element is larger, it should be after the second element in the sorted array.
- Based on the above conventions, the implementation of the function Bubblesort () is as follows, and Quicksort () is slightly more complicated:
void DLLDIR__stdcall Bubblesort (byte * array, intsize, intelem_size, cmpFunc) { for (inti = 0; i <size; i ++) { for (intj = 0; j <size-i-1; j ++) { // Callback comparison function if (1 == (* cmpFunc) (array + j * elem_size, array + (j + 1) * elem_size)) { // Two compared elements are exchanged byte * temp = newbyte [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 memcpy () is used in the implementation, the function will be limited in terms of the data types used.
- For the user, there must be a callback function whose address is passed to the Bubblesort () function. Here are two simple examples, one comparing two integers and the other comparing two strings:
int__stdcall CompareInts (constbyte * velem1, constbyte * velem2) { int elem1 = * (int *) velem1; int elem2 = * (int *) velem2; if (elem1 <elem2) return-1; if (elem1> elem2) return1; return0; } int __stdcall CompareStrings (constbyte * velem1, constbyte * velem2) { const char * elem1 = (char *) velem1; const char * elem2 = (char *) velem2; return strcmp (elem1, elem2); }
- Here is another program that tests all the above code. It passes an array of 5 elements to Bubblesort () and Quicksort (), and also passes a pointer to a callback function. (Use the byte type to include the header file windows.h, or
typedef unsignedchar byte;
int main (intargc, 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,10, & CompareStrings); cout << "After the sorting \ n"; for (i = 0; i <5; i ++) cout << str [i] << '\ n'; return0; }
- If you want to sort in descending order (large elements first), you only need to modify the code of the callback function, or use another callback function, so that the programming flexibility is greater.
Callback function calling convention
- In the above code, __stdcall can be found in the function prototype, because it starts with a double underscore, so it is a compiler-specific extension, which is Microsoft's implementation in the final analysis. Any support for developing Win32-based programs must support this extension or its equivalent. The functions identified by __stdcall use the standard calling convention. Why is it called the standard convention, because all Win32 APIs (except those that accept variable parameters individually) use it. Standard calling convention functions remove parameters from the stack before they return to the caller. This is also Pascal's standard convention. However, in C / C ++, the calling convention is that the caller is responsible for cleaning up the stack, not the called function; to force the function to use the C / C ++ calling convention, __cdecl can be used. In addition, variable parameter functions also use the C / C ++ calling convention.
- The Windows operating system uses the standard calling convention (Pascal convention) because it can reduce the size of the code. This was very important for early Windows, because it was running on a computer with only 640KB of memory.
- If you don't like __stdcall, you can also use the CALLBACK macro, which is defined in windef.h:
#define CALLBACK__stdcallor #define CALLBACKPASCAL // and PASCAL is #defined to __stdcall
- C ++ method as callback function
- Because I usually use C ++ to write code, I may think of writing the callback function as a method in the class, but first look at the following code:
class CCallbackTester { public: int CALLBACKCompareInts (constbyte * velem1, constbyte * velem2); }; Bubblesort ((byte *) array, 5, sizeof (array [0]), & CCallbackTester :: CompareInts);
- If you use the Microsoft compiler, you will get the following compilation error:
errorC2664: 'Bubblesort': cannotconvertparameter4from'int (__ stdcallCCallbackTester :: *) (constunsignedchar *, constunsignedchar *) 'to'int (__ stdcall *) (constunsignedchar *, constunsignedchar *)' There is no context in which this conversion is possible
- This is because non-static member functions have an extra parameter: the this pointer, which will force you to put static in front of the member function.