views:

111

answers:

4

Are callback functions equivelent to events in C#(.NET).

What I understand about callback function is, it is a function that is called by a reference to that Function.

Example Code will be:

void cbfunc()

{
        printf("called");
 }

int main ()

{

    void (*callback)(void);

    callback=(void *)cbfunc;

   callback();

   return 0;

}

Now What I dont understand is How is this use full with respect to notifying from the DLL to client.

Suppose I want to do /perform some method1() when I recieve Data on my DLL method2().

Any comparasion with Events in .NET will be helpfull in a great way.

+1  A: 

You pass the pointer to a 3rd-party routine (doesn't have to be a DLL) and it is "called back" when notificastion is required, by the cloned pointer.

It is similar to .net events in that the latter are also a type of a callback.

BTW, DLLs are less popular in C++ than they are in .NET. This is due to impossibility of sharing static variables (and therefore, singletons), the problem also known as lack of dynamic linking (in UNIX systems, this is solved with Shared Objects, which are quite a different concept of dynamically loaded library). Static libraries offer a better code reuse strategy.

Pavel Radzivilovsky
+1  A: 

Callback functions fulfill a similar purpose to delegates in C#.

For example, the Win32 API provides a timing service, that is accessed by calling SetTimer. SetTimer is exported by a system DLL, but the mechanism is exactly the same as if used in a user dll. In your code you would access the timer by doing something like this:

void 
CALLBACK
MyTimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
// do something
}

...

TIMERPROC fn = &MyTimerCallback;
int delay = 500;  
SetTimer(NULL,0,delay,fn); 

Calling SetTimer, and passing in the callback function, allows the operating system to call back into the function each time the timer ticks. Of course, there is no multicast capability here, and, especially in the case of SetTimer, the callback function must be a C function or static class method. There is no class or object instance associated with the function.

A similar pattern could be done in .NET - Im sure .NET has its own Timer paradigm but for a moment we could pretend that it implements a SetTimer function that takes a TimerDelegate.

In user code, in an object you would then define the MyTimerProc as a function with a signature that matches the delegate. And invoke it like this

TimerDelegate d = new TimerDelegate(myObject.MyTimerProc);
SetTimer(0,0,delay,d);

Or, if "timers" was an event that matched the TimerDelegate, then the equivalent C# code would look something like:

timers += new TimerDelegate(myObject.MyTimerProc);

Note: My C# is very rusty so don't take those code samples as any kind of example of either best practices, or even working code :P


When defining your own callback functions it is good practice to always define callback functions to take a void* "context" parameter, as that allows C++ programmers to store their "this" pointer and retrieve it.

// the first parameter to the callback fn is a void* user supplied context parameter
typedef void (CALLBACK* MyCallbackFn)(void* context, int etc);

// and, the dll export function always takes a function pointer, context parmeter pair.
DLL_EXPORT void SomeExportedFn(MyCallbackFn, void* context);
Chris Becke
+1  A: 

Callbacks and interface classes are great ways to manage your code boundaries. They help create formal boundaries and/or layers in your code instead of lumping everything together. This becomes necessary when working on large software solutions.

Below is an example of how to use callbacks and interface classes. In the library/dll code the only thing that should be exposed to the main executable is the myddl_interface class and the function getMyDllInterface(). Using an interface class like this completely hides the implementation detail from the main executable. The interface class also allows the main executable to register a function with it that will be executed later (i.e. callback).

// Begin library/dll Public Interface used by an executable
class mydll_interface {  
public:  
    typedef void (*callback_func_t)();  
public:  
    virtual void do_something() = 0;  
    virtual void registerFunction( callback_func_t ) = 0;  
};  

static mydll_interface* getMyDllInterface();

// End library/dll Public Interface used by an executable

// Begin library/dll Private implementation
class mydll_implementation : public mydll_interface {  
public:  
    void do_something() {  
        printf("Hello World\n");  
        _callback_func();  
    }  
    void registerFunction( callback_func_t c) {  
        _callback_func = c;  
    }  
private:  
    callback_func_t _callback_func;  
};  

static mydll_interface* getMyDllInterface() {  
    return new mydll_implementation();  
};  
// End library/dll Private implementation

// Begin main executable code
void myMainAppFunc() {  
    printf("hello World Again\n");  
}  

int main() {    
    mydll_interface* iface = getMyDllInterface();  
    iface->registerFunction(&myMainAppFunc);  
    iface->do_something();  
};  
// End main executable code
skimobear
A: 

A notable example is qSort(), it needs a callback function to compare 2 items. Callback function can leave some behavior decided at runtime.

If some behavior should be decided by client side dynamically at runtime, then I will ask clients to supply callback functions.

Toro