Chen Jiapeng (japen@vip.sina.com) February 2004 What is a certain interface between the callback software module, from the call mode, you can divide them into three categories: synchronous call, callback and asynchronous call . Synchronous call is a blocking call, the call party must wait for the other party to return, it is a one-way call; the callback is a two-way call mode, that is, the called party is called when the interface is called. The other party's interface; asynchronous calls are a mechanism for similar messages or events, but its calling direction is just in contrast, and the interface is actively informing the client when receiving a message or something happens. Interface). The relationship between the callback and asynchronous calls is very close, usually we use the callback to realize the registration of asynchronous messages, and notifications of messages through asynchronous calls. Synchronous calls are the simplest, and the callback is often the basis of asynchronous calls, so we focus on the implementation of the callback mechanism in different software architectures.
For different types of languages (such as structural language and object language), platform (Win32, JDK), or Corba, DCOM, WebService, customer and service, in addition to synchronization, there is a certain asynchronous notification mechanism, Let the service party (or interface provider) can actively inform the customer in some cases, while the callback is a simplest way to achieve asynchronous.
For a general structured language, callback can be achieved by callback function. The callback function is also a function or process, but it is a special function that is implemented by the calling party for use by the caller.
In the object-oriented language, the callback is implemented by an interface or abstract class. We make the class that implements this interface into a callback class, and the callback class is a callback object. For object languages that are compatible with C or Object Pascal, it is also provided with the characteristics of the callback object, the callback method, but also compatible with the callback function mechanism of the process language.
The message mechanism of the Windows platform can also be regarded as an application of the callback, and we register the message processing function (ie the callback function) through the system provided, so that the purpose of receiving, processing the message. Since the API of the Windows platform is built with C language, we can think it is also a special case of the callback function.
For distributed component agent CORBA, there are various ways, such as callback, event service, notification service, etc. Event service and notification services are standard services for CORBA to handle asynchronous messages, and they are responsible for the processing, distribution, maintenance of messages. For some simple asynchronous processing, we can be implemented by a callback mechanism.
Below we focus on comparing representative language (C, Object Pascal) and architecture (CORBA) to analyze the implementation of the callback, the specific functions.
2 Power in the process language (c)
2.1 function pointer
The callback is implemented by a function pointer in the C language. By transmitting the address of the callback function to the modified function to achieve the callback. Therefore, to achieve a callback, you must first define a function pointer, please see the example below:
Void func (char * s); // function prototype
Void (* pfunc) (char *); // function pointer
It can be seen that the definition of the function is very similar to the definition of the function pointer.
Generalization, in order to simplify the variable definition of the function pointer type, improve the readability of the program, we need to customize the function pointer type.
TypeDef void (* pcb) (char *);
The callback function can be called like a normal function, but only it is called a callback function when it is passed as a parameter to the called function.
Example of the modulated function: Void getCallback (PCB Callback)
{
/ * Do Something * /
}
When the user calls the above function, you need to implement a PCB type callback function yourself:
Void fcallback (char * s)
{
/ * Do Something * /
}
Then, you can directly pass the FCallback as a variable to getCallback.
GetCallback (fcallback);
If the different values are assigned to this parameter, the caller will call a function of different addresses. The assignment can occur when running, so that you can realize dynamic binding.
2.2 Parameter transfer rules
So far, we only discuss the function pointer and callback without paying attention to the compiler specification of ANSI C / C . Many compilers have several invoking specifications. For example, in Visual C , you can add _cDecl, _stdcall, or _pascal in front of the function type, indicate its call specification (default to _cDecl). C Builder also supports _fastcall call specification. Call specification affects the given function name generated by the compiler (from right to left or from left to right), stack cleaning responsibility (caller or called by caller) and parameter transfer mechanism (stack, CPU register, etc.) .
It is important to see that the call specification is part of the function type; the address cannot be assigned to the function pointer with an incompatible call specification. E.g:
// The modified function is parameter with INT, with INT is returned value
__stdcall int callee (int);
// Call function as a function pointer as a parameter
Void Caller (__CDECL INT (* PTR));
/ / Illegally operated in P-Phase Phaseo
__cdecl int (* p) (int) = Callee; // error
The types of pointers P and Callee () are not compatible because they have different call specifications. Therefore, it is not possible to assign the address of the caller to the pointer P, although the two have the same return value and the parameter column.
2.3 Application Examples
Among the C language standard library functions, the callback function is used to let the user customize the process. Such as common rapid sort functions, secondary search functions, etc.
Quick Sort Function Prototype:
Void Qsort (void * base, size_t nlem, size_t width, int (_USERENTRY * FCMP) (Const void *, const void *);
Debut search function prototype:
Void * bsearch (const void * key, const void * base, size_t nlem, size_t width, int (_USERENTRY * FCMP) (Const void *, const void *));
Where FCMP is a variable of a callback function.
A specific example is given below:
#include
#include
INT Sort_function (const void * a, const void * b);
INT List [5] = {54, 21, 11, 67, 22};
Int main (void)
{
INT X;
Qsort (void *) list, 5, sizeof (list [0]), sort_function;
FOR (x = 0; x <5; x )
Printf ("% I / N", list [x]);
Return 0;
}
Int sort_function (const void * a, const void * b) {
Return * (int *) a - * (int *) b;
}
2.4 Tune in object-oriented language (Delphi)
DEPHI is the same as C , in order to maintain compatibility with process language, it retains previous structured characteristics while introducing an object-oriented mechanism. Therefore, there are two distinct modes of the callback, one is a structured function callback mode, one is an object-oriented interface mode.
2.4.1 callback function
Tune function type definition:
Type
TCALCFUNC = Function (A: Integer; B: Integer): Integer;
Customize the implementation of the function according to the format of the callback function, such as
Function Add (A: Integer; B: Integer): Integer
Begin
Result: = a b;
END;
Function SUB (A: Integer; B: Integer): Integer
Begin
Result: = a-b;
END;
Callback
Function Calc (CALC: TCALCFUNC; A: Integer; B: Integer: Integer
Below, we can call these two functions in our program.
C: = Calc (add, a, b); // c = a b
C: = Calc (SUB, A, B); // C = A-B
2.4.2 Tune Object
What is the callback object, which occasion is it used? First, let's compare it with the callback function, the callback function is a prototype that defines the function, and the function body is subjected to a dynamic application mode implemented by the third party. To achieve a callback function, we must clearly know how to: This function requires those parameters, returning what type of value. Similarly, a callback object is also an abstract class (ie, an interface) that defines the object interface, but there is no specific implementation. To implement a callback object, we must know: What methods do it need to implement, and what parameters in each method, what is the value needs to be returned.
Therefore, in the application mode of the callback object, we will use the interface. The interface can be understood as a class defined but not implemented, which can only be implemented by other classes by inheritance. The interfaces and COM interfaces in Delphi are similar, and all interfaces are inherited with IINTERFACE (equivalent to IUNKNOW) and to implement three basic methods queryinterface, _addref, and _Release.
Define an interface
Type ishape = interface (Iinterface)
Procedure draw;
end
Implement a callback class
TYPE TRECT = Class (Tobject, ISHAPE)
protected
Function QueryInterface (Const IID: Tguid; Out Obj): hResult; stdcall;
Function _addref: integer; stdcall;
Function _Release: integer; stdcall;
public
Procedure draw;
END;
Type tround = Class (Tobject, IShape)
protected
Function QueryInterface (Const IID: Tguid; Out Obj): hResult; stdcall;
Function _addref: integer; stdcall;
Function _Release: integer; stdcall; public
Procedure draw;
END;
Use a callback object
Procedure MyDraw (Shape: ishape);
VAR
Shape: ISHAPE;
Begin
Shape.draw;
END;
If the incoming object is TRECT, then draw a rectangle; if true, it is a circular. Users can also implement the ISHAPE interface according to their intentions, draw their own graphics:
MyDraw (TRECT.CREATE);
MyDraw (Tround.create);
2.4.3 Torp Method
Callback Method can be seen as part of the callback object, and Delphi has the concept of callback method for Windows messages. In some cases, we don't need to implement the entire object in accordance with a given request, and as long as one of them can be implemented, this is what we will use the callback method.
The definition of the callback method is as follows:
TNOTIFYEVENT = Procedure (Sender: TOBJECT) OF Object
TMYEVENT = procedure (sender: TOBJECT; EventID: integer) OF Object;
TNOTIFYEVENT is the most commonly used callback method, form, and a lot of events in Delphi. If you click on events, shutdown events, TNOTIFYEVENT. The variable of the callback method is generally defined by the event attribute, such as the definition of the Create event of TCUSTOMForm:
Property Oncreate: TNotifyEvent Read Foncreate Write Foncreate Stored Isform
We can customize the event processor by assigning values to event attribute variables.
User-defined objects (objects containing callback methods):
Type tcallback = Class
Procedure ClickFunc (Sender: TOBJECT);
END;
Procedure tcallback.clickfunc (sender: TOBJECT);
Begin
ShowMessage ('The Caller is Clicked!');
END;
Form object:
TYPE TCUSTOMFRM = Class (TFORM)
public
Procedure RegisterClickFunc (CB: Procedure (Sender: Tobject) OF Object);
END;
Procedure TCUSTOMFRM..REGISTERCLICKFUNC (CB: TNOTIFYEVENT);
Begin
SELF.ONCLICK = CB;
END;
Instructions:
VAR
FRM: TCUSTOMFRM;
Begin
FRM: = TCUSTOMFRM.CREATE (APPLIC);
Frm.registerClickFunc (TCALLBACK.CREATE (). ClickFunc);
END;
3 Application of callback in distributed calculation (CORBA)
3.1 Tune Interface Model
There are many kinds of Corba's messaging mechanism, such as callback interface, event service, and notification service. The principle of the callback interface is simple, CORBA customers and servers have dual roles, ie servers are also customer customers.
The reverse call of the callback interface is often performed simultaneously. If the callback interface is called multiple times, the callback interface becomes an asynchronous interface. Therefore, the callback interface often serves as an event registration in CORBA. When the client calls the registration function, the customer function is the callback function. In this call, the function is to achieve an asynchronous asynchronous because there is no need to actively participate in the client. mechanism. From the CORBA specification, we know that a CORBA interface has different performance forms in the server and the client. In the client generally uses the pile (STUB) file, the server is used to the frame (Skeleton) file, the interface size is defined by IDL . The introduction of the callback function makes the server and the client need to achieve a certain pile and framework. Below is the realization model of the callback interface:
3.1.1 Example
The following is given an interface file that uses a callback. The server needs to implement the framework of the Server interface, the client needs to implement the Callback framework:
Module CB
{
Interface callback;
Interface server;
Interface Callback, INTERFACE
{
Void Onevent (In Long Source, IN Long MSG);
}
Interface Server
{
Long RegisterCB (in Callback CB);
Void UnregisterCB (in long hcb);
}
}
The client first calls the server interface registcb by synchronizing, and is used to register the callback interface Callback. After receiving the request, the server will retain the interface reference. If some event needs to be notified to the client, the client's Onevent function is called, so that the other party will process in time.