The callback function is written by yourself. You need to call another function. One of the parameters of this function is
It is your callback function name. In this way, the system will call the callback function you write when necessary, so that you can
To complete what you want to do in the callback function.
Module A has a function Foo, which transmits the foo address to Module B, And then when an event occurs in Module B, call Foo through the foo address passed in from A to notify a of what happened and let a respond accordingly. Then we call Foo a callback function.
Example:
A callback function is a very useful and important concept. When an event occurs, the system or other functions automatically call a function. Callback functions are widely used in Windows programming, such as hook callback functions: mouseproc, getmsgproc, enumwindows, and drawstate callback functions. There are also many system-level callback processes. This article will not introduce these functions and procedures, but will talk about some experiences in implementing your own callback functions.
The idea of using a callback function is generated because a DLL program written by VC is used for some long asynchronous work, applications that need to be notified to use dll: Some events have been completed. process the subsequent parts of the event. I first thought about how to use the synchronization object, file ing, messages, and other DLL functions to send notifications to the application. Then I suddenly thought that I could write a function at the application end, when you need to deal with subsequent issues, you can directly call this function in the DLL.
So I wrote the original form of a callback function. Both VC and Delphi have been tested.
I. Declare the callback function type.
VC version
Typedef int (winapi * pfcallback) (INT param1, int param2 );
Delph
Pfcallback = function (param1: integer; param2: integer): integer; stdcall;
In fact, it declares that the return value is int, and the input parameter is the pointer to the function of two int values.
Since the C ++ and Pascal compilers may have different processing methods for parameter input stack and function return, the function types are modified in a unified manner using winapi (winapi macro expansion is _ stdcall) or stdcall.
Ii. Declare the original form of the callback function
Declared function prototype
VC version
Int winapi cbfunc (INT param1, int param2 );
Delphi Edition
Function cbfunc (param1, param2: integer): integer; stdcall;
The above functions are global functions. If you want to use a function in a class as the original form of the callback function, declare the function as a static function.
Iii. Callback Function caller
I put the callback function into the DLL. This is a very simple Win32 DLL generated by VC, and uses the def file to output the function name testcallback. The implementation is as follows:
Pfcallback gcallback = 0;
Void winapi testcallback (pfcallback func)
{
If (func = NULL) return;
Gcallback = func;
DWORD threadid = 0;
Handle hthread = createthread (null, null, thread1, lpvoid (0), & threadid );
Return;
}
This function saves the input pfcallback func parameter for use and starts a thread. Declares a function pointer pfcallback gcallback to save the input function address.
4. How to Use the callback function:
After the testcallback function is called, a thread is started. As a demonstration, the thread manually delays processing and prints the thread running process on the screen.
The code of this thread is also implemented in the DLL project.
Ulong winapi thread1 (lpvoid PARAM)
{
Tchar buffer [256];
HDC = getdc (hwnd_desktop );
Int step = 1;
MSG;
DWORD starttick;
// A delay Loop
For (; Step <200; Step ++)
{
Starttick = gettickcount ();
/* This section refers to the part of the thread's running time for the system to process other transactions */
For (; gettickcount ()-starttick <10 ;)
{
If (peekmessage (& MSG, null, 0, 0, pm_noremove ))
{
Translatemessage (& MSG );
Dispatchmessage (& MSG );
}
}
/* Print the running state to the desktop. This is the favorite task of vcbear debugging */
Sprintf (buffer, "Running % 04d", step );
If (HDC! = NULL)
Textout (HDC, 30, 50, buffer, strlen (buffer ));
}
/* Call the callback function after a delay period */
(* Gcallback) (step, 1 );
/* End */
: Releasedc (hwnd_desktop, HDC );
Return 0;
}
5. Everything is ready
A project is created using VC and Delphi, and the Implementation part of the callback function is written.
VC version
Int winapi cbfunc (INT param1, int param2)
{
Int res = param1 + param2;
Tchar buffer [256] = "";
Sprintf (buffer, "Callback result = % d", Res );
MessageBox (null, buffer, "testing", mb_ OK); // demonstrate that the callback function is called
Return res;
}
Delphi Edition
Function cbfunc (param1, param2: integer): integer;
Begin
Result: = param1 + param2;
Tform1.edit1. Text: = inttostr (result); // demo callback function called
End;
Use the static connection method to connect to the exit function testcallback In the DLL, and add a button in the project (for the Delphi project, you also need to put an edit control on form1, the default name is edit1 ).
Call testcallback in response to the buttonclick event
Testcallback (cbfunc) // The cbfunc parameter of the function is the address of the callback function
The function call will return immediately after the thread is created, and the application can do other things at the same time. Now we can see that the screen keeps displaying strings, indicating that the threads created in the DLL are running normally. After a while, the thread delay ends. The MessageBox pops up in the VC application, indicating that the callback function is called and the result of param1 and param2 operations is displayed, the text in the edit control of Delphi Program is rewritten to the calculation result of param1 and param2.
It can be seen that different callback function addresses can be transferred according to different requirements using the callback function programming mode, you can also define the prototype of various callback functions (you also need to change the parameters and return value conventions of the callback function) to handle multiple callback events, so that program control is flexible and variable, it is also an efficient and clear coupling method between program modules. It is particularly useful in some asynchronous or complex program systems-you can concentrate on implementing the core business processes and technical functions of the module in a module (such as DLL, the peripheral extended functions only provide one callback function interface. by calling the callback function address passed by other modules, the subsequent processing is seamlessly handed over to another module, as it is processed in a custom way.
The example in this article uses the method of calling the callback function after the multi-thread delay in the DLL, just to highlight the effect of the callback function, as long as it is within the process, you can use the function address as the callback function.
The principle of such a programming mode is very simple and simple: the function is also called as a pointer and an address. There is nothing complicated, just a small skill in programming. As for how much benefit the callback function mode can bring to you, it depends on whether you use it and how to use this programming mode.
Another explanationCdxiaogan
As mentioned on msdn:
Knowledge about function pointers
Examples can be used to describe the usage of function pointers. First, take a look at the enumwindows function in Win32 API:
Declare function enumwindows lib "USER32 "_
(Byval lpenumfunc as long ,_
Byval lparam as long) as long
Enumwindows is an enumeration function that lists the handles of each opened window in the system. The way enumwindows works is to repeatedly call the first parameter passed to it (lpenumfunc, function pointer ). Every time enumwindows calls a function, enumwindows passes a handle to open the window.
When calling enumwindows in code, you can pass a UDF to it as the first parameter to process a series of values. For example, you can write a function to add all values to a list box, convert the hwnd value to the window name, and perform any other operations!
To indicate that the passed parameter is a custom function, add the addressof keyword before the function name. The second parameter can be any suitable value. For example, if you want to use myproc as a function parameter, you can call enumwindows in the following way:
X = enumwindows (addressof myproc, 5)
The custom function specified during the call process is called a callback function. A callback function (usually called "Callback") can perform specified operations on the data provided in the process.
The parameter set of the callback function must have a specified form, which is determined by the callback function API. For more information about the required parameters and how to call them, see the API documentation.
Reply:Zcchm
Let me talk about my understanding of the callback function. If not, please advise.
I was confused when I first started to contact callback. when many people explain this problem, they always use APIs for example. Originally, cainiao was most afraid of API, ^_^. callback is not necessarily related to the API.
In fact, callback is a process of using a function pointer to call a function.
Why callback? For example, I want to write a sub-module for you to receive commands sent from remote socket. after receiving the command, I need to call the function of your main module for corresponding processing. but I don't know which function you want to use to process this command, and I don't know what your main module is. CPP or. h, or, I don't have to worry about how you handle it in the main module, or what functions should be used to process it ...... what should I do?
Use callback.
In my module, I first define the callback function type and the callback function pointer.
Typedef void (callback * cbksenddomaintomain) (ansistring scmd );
Cbksenddomaintomain senddomaintomain;
In this way, senddomaintomain is a function pointer pointing to an ansistring parameter with a return value of void.
In this way, you can call this function when I receive the command.
...
Senddomaintomain (scommand );
...
But this is not enough. I have to give an interface function (such as init) so that you can call init in the main module to register this callback function.
In your main module, this may happen.
Void callback yoursendcmdfun (ansistring scmd); // declare
...
Void callback yoursendcmdfun (ansistring scmd); // define
{
Showmessage (scmd );
}
...
Call the init function to register a callback with my module. This may be the case:
Init (yoursendcmdfun ,...);
In this way, the expected goal is achieved.
Note that the callback function must be declared as global. If you want to use the callback function in the class, you need to add static before, which is actually equivalent to global.