C++ Callback Demo
This article was contributed by Elmue.
Environment: Pure C++. Runs on Windows, Mac, Linux, and so on.
Introduction
This fully functional example shows how in C++ callbacks can be done in an absolutely flexible way!
This demo is written in Visual Studio 6 but the Callback class is platform independent and also runs under Linux, Mac, and so forth....
Callbacks in C++ are not as simple as in C. Pure C functions are from the type __cdecl. C++ functions are from the type __thiscall. (They differ in the way how they pass arguments on the stack.)
In C++, you have classes and, additionally, instances of classes. Every instance uses its own memory area for storing class variables. The pointer to this area of variables is the "this" pointer. It represents the instance. Every time you call any C++ function, the "this" pointer is passed to the function as an invisible parameter! (M$ Visual Studio 6 uses the processor register ECX to pass the "this" pointer.)
So, in C++ it is not enough to store the address of the function, which you want to call back. You also have to store the "this" pointer!
Using the Callback Class
You can include "Callback.h" into your project. The usage it is very simple because the cCallback class has only two member functions: SetCallback() and Execute(). You can understand the following examples without knowing what is happening inside cCallback.
cMyProject.h:
#include "callback.h"
private:
// the functions of your project
void CallbackFox (int Param);
void CallbackRabbit(int Param);
void TestTheCallback(cCallback *pCallbackFunction, int Param);
// Some instances of the Callback class
TCallback<cMyProject> i_Callback_1;
TCallback<cMyProject> i_Callback_2;
cMyProject.cpp:
void cMyProject::CallbackRabbit(int Param)
{
char Buf[50];
sprintf(Buf, "Now I'm in Rabbit with Param %d !\n", Param);
printf(Buf);
}
void cMyProject::CallbackFox(int Param)
{
char Buf[50];
sprintf(Buf, "Now I'm in Fox with Param %d !\n", Param);
printf(Buf);
}
void TestTheCallback(cCallback *pCallbackFunction, int Param)
{
pCallbackFunction->Execute(Param * Param);
}
void cMyProject::CallbackDemo()
{
// defining where the callback should jump to
i_Callback_1.SetCallback(this, &cMyProject::CallbackRabbit);
i_Callback_2.SetCallback(this, &cMyProject::CallbackFox);
// now you can pass i_Callback like a pointer to a function
TestTheCallback(&i_Callback_1, 4);
TestTheCallback(&i_Callback_2, 5);
}
If you call cMyProject::CallbackDemo(), the output will be:
Now I'm in Rabbit with Param 16 ! Now I'm in Fox with Param 25 !
Callback Re-Definitions
It is also possible to re-define the callback with SetCallback() as often as you like:
void cMyProject::CallbackDemo()
{
i_Callback_1.SetCallback(this, &cMyProject::CallbackRabbit);
TestTheCallback(&i_Callback_1, 4);
i_Callback_1.SetCallback(this, &cMyProject::CallbackFox);
TestTheCallback(&i_Callback_1, 5);
}
The output would be the same, but i_Callback_2 is not needed anymore.
Callback Arrays
It is also possible to use arrays of callbacks:
cMyProject.h:
private:
TCallback<cMyProject> i_Callback[10];
cMyProject.cpp:
void TestTheCallback(int Index, int Param)
{
i_Callback[Index].Execute(Param * Param);
}
void cMyProject::CallbackDemo()
{
i_Callback[0].SetCallback(this, &cMyProject::CallbackRabbit);
i_Callback[1].SetCallback(this, &cMyProject::CallbackFox);
i_Callback[2].SetCallback(.....);
TestTheCallback(0, 4);
TestTheCallback(1, 5);
}
Callback Arrays, Part 2
In the above example, all callbacks are from cMyProject. In i_Callback you can ONLY store callbacks to the cMyProject class because it is defined as TCallback<cMyProject>.
If you want to store callbacks to different classes in a callback array, you have to create the array from cCallback instead of TCallback:
cMyProject.h:
private:
cCallback *p_Callback[10];
cMyProject.cpp:
void cMyProject::StoreCallback(cCallback *p_CallbackFunction,
int Index)
{
p_Callback[Index] = p_CallbackFunction;
}
StoreCallback() then can be called by ANY class to set a callback to itself. For example:
cDemo.h:
private:
TCallback<cDemo> i_MyCallback;
cDemo.cpp:
#include "cMyProject.h"
extern cMyProject i_MyProject;
......
i_MyCallback.SetCallback(this, &cDemo::MyCallbackFunction);
i_MyProject.StoreCallback(&i_MyCallback, Index);
......
You can even later modify i_MyCallback with SetCallback() without having to call StoreCallback() again!!
In the source code (see the download link at the end of this article) you find a different example, and additionally a demonstration of a global callback, which you need, if you want to be called back by the operating system. (Windows API callbacks always go into the global namespace.)
The Callback Class
Finally, here comes the great cCallback class itself. It consits of only a header file without a corresponding cpp file.
Callback.h:
class cCallback
{
public:
virtual void Execute(int Param) const =0;
};
template <class cInstance>
class TCallback : public cCallback
{
public:
TCallback() // constructor
{
pFunction = 0;
}
typedef void (cInstance::*tFunction)(int Param);
virtual void Execute(int Param) const
{
if (pFunction) (cInst->*pFunction)(Param);
else printf("ERROR : the callback function has not
been defined !!!!");
}
void SetCallback (cInstance *cInstancePointer,
tFunction pFunctionPointer)
{
cInst = cInstancePointer;
pFunction = pFunctionPointer;
}
private:
cInstance *cInst;
tFunction pFunction;
};
This class defines an Execute() function that takes one integer parameter and returns no parameter (void). You can simply adapt it to your needs; for example, a callback that takes five paramaters and returns a bool. (Then, you have to modify three lines: the two lines beginning with "virtual void Execute" and the typedef.)
To completely understand this class, you need advanced C++ knowledge. I will not explain all the details here because this would be too much.
Instead I recommend the very good book:
Author: André Willms
Title: C++ Programming (German title: "C++ Programmierung")
Publisher: Addison Wesley
ISBN 3-8273-1495-X
And from my homepage, you can download free C++ books in the compiled HTML format.

Comments
Michael Kors Purses
Posted by gogofkn on 05/14/2013 06:13pmI'm looking at your site through Google Chrome and not each of the pictures is displaying right. Did you know about this? toms shoes sale toms shoes ray ban
Replyhttp://www.tomsoutletw.com/ bxmaob
Posted by http://www.tomsoutletw.com/ Mandyyad on 03/30/2013 12:07pmoakley sunglasses,Younger brother is the sworn brother to sworn to Your brother the Monkey King Torr World ah! Cattle devil looked at the familiar face goes, several hundred years later, finally appeared in front of him, think carefully, after he identified. To know Princess Iron Fan's affair in mind so that his head green cap is still green, that is a huge shame his life! His disgrace in the demon world face the pain of the man than this! Is the little brother ray ban wayfarer ah! Monkey King saw the astonished face cow devil I know Me, then quickly respond cattle devil face with a happy, his Deyizhiyu also did not care about his side the Jingjing Hechun 30th Niang face of surprising and strange, or else he will not respond so readily and excitement. ray ban wayfarer sizes kill you hook her sister-in-law of anti-bone Aberdeen!oakley sunglasses discount,raybansunglassesouty.com/" title="ray ban clubmaster"ray ban clubmaster, Cattle devil confirmed after the fact, immediately toward Monkey King swallowed their anger, waving his big fork, want killed and outlet.
Replycheap ugg boots vEsr mMgh
Posted by Suttonjge on 03/09/2013 05:19ammichael kors bags nfaswndu michael kors handbags zgtumsfn michael kors outlet mmxqxuvd michael kors purse ehvtikeg michael kors purses aeevevwh michael kors sale zagkrigz michael kors pccdklkx
Replyghd australia jbraod
Posted by Mandyglh on 02/03/2013 05:41pm7uXdj ugg pas cher vDlh ¥åê©`¥é`¥à ¥Ã¥å° fLsq nike sko 7nQez cheap toms 3aFkr cheap hollister 1tDmb bottes ugg 1oHau longchamp pliage 1mSfv cheap louis vuitton 7aBci michael kors bags 7xTls christian louboutin norge 9cThe 49ers jerseys 2cCko 1nKet GHD Australia 1zHbl Lisseur GHD 9gJwt ugg boots sale
Replyugg boots alwpoy http://www.cheapfashionshoesas.com/
Posted by Mandyqep on 01/26/2013 11:00pm2gJpu nike outlet mMji Michael Kors outlet wJsu ugg boots 7nKrj monster beats 6dZnx Cheap nfl jerseys 7eXes ugg norge 8tWdk burberry outlet 9vAfu longchamp 8nWyg nike air max 7kEuf cheap ugg boots 0eOvx monster beats 7wSib ugg 1gBsw GHD Australia 4lMjo 5xWux
Replyhttp://achattdoudounemonclairsonline.webnode.fr/ wfhkjt vrzkiu
Posted by rootlyJerie on 11/15/2012 03:49amC++ Callback Demo pfdkxs ptjlclk adgkly doudoune moncler bqeqosd lvusbcgu doudoune moncler femme gozerck ymxmz moncler france cigseoee moncler france cufjsdxb abercrombie vbzjzhbg
Replyhttp://doudouneemonclairmagasinns.blogspot.com/ lydwry olymbf
Posted by PambInabe on 11/10/2012 11:51pmC++ Callback Demo mhzdmu smbojfx sefypk polo ralph lauren uk przmcoe chplrgbb ã¢ãã£ã¼ãf50 rxmmgif sgufr air ã¸ã§ã¼ãã³ qtdlfauq ããã·ã£ã ltzrkrqe ã´ã£ãã³ ã¢ãã°ã©ã jcywkkqd
ReplyA good example
Posted by kora3 on 05/26/2009 04:40amA good example for beginners to learn how to implement callbacks.
ReplyA method for using callbacks in a c++ class
Posted by Legacy on 07/30/2003 12:00amOriginally posted by: Wayne
Hello, some good points and methods have been discussed. I’m by no means an expert on callbacks but recently I wanted to use an SNMP callback function and have it be part of a C++ class (without the draw backs of making it static) I have use this same technique before with threads (_beginthreadex). Anyway here is my solution.
The API I wanted to use was SnmpCreateSession() which can post a message to a window queue or call a callback function. I wanted to use the callback.
Here is the final API call.
m_hSession = SnmpCreateSession (NULL, 0, CallBackFunc , NULL);
The name of my class is SNMPLISTEN witch is derived from a class ThreadObject.
(this doesn’t matter but it helps clarify the code)
In another file I declared a global pointer (pointer to the base class)
//----------------------------------------------------------
extern ThreadedObject *gpSnmpClass;
//----------------------------------------------------------
class SNMPLISTEN : public ThreadedObject
{ ….
Private:
//Func that does the real work
SNMPAPI_STATUS ProcessCallBack(HSNMP_SESSION hSession, HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam, LPVOID lpClientData );
//func that gets called by OS
inline static SNMPAPI_STATUS CALLBACK CallBackFunc(HSNMP_SESSION hSession, HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam, LPVOID lpClientData)
{
SNMPLISTEN *pObject = (SNMPLISTEN*) gpSnmpClass;
return pObject->ProcessCallBack(hSession, hWnd, wMsg, wParam, lParam, lpClientData );
}
….}; //end class
//---------------------------------------------------------
SNMPLISTEN class constructor
SNMPLISTEN::SNMPLISTEN(const char *objectTag, bool *startup) : ThreadedObject(objectTag)
{…
gpSnmpClass = this;
…}
//---------------------------------------------------------
The function CallBackFunc() gets called by the OS and then uses a pointer to call a member function ( ProcessCallBack() ) that isn’t static and pass along the params. The ProcessCallBack can then access class member vars and functions.
ReplyThis probably isn’t the perfect or most elegant solution. I hope it might help some else out.
But why function pointers?
Posted by Legacy on 07/29/2003 12:00amOriginally posted by: Ben
First, bravo! It's a good example of how to use function pointers in C++.
Second, I wonder, in this day and age, why we would want to be using such things? Because we can? Sure, if your goal is to discover the beautiful language that C++ is.
However, I believe there are better ways to implement callbacks that are more robust, flexible and OOP correct. In my experience, callbacks are commonly used for two things: event notification and provide framework classes.
For event notification, I believe it is best to have the event handler implement an interface ("subclass an abstract class" in C++ talk) and then the generator of events keeps a set of objects interested in notification of event. This is documented in the "Observer pattern" by the GoF.
For framework classes, you want to offer basic services and let the user define the details. For instance, a set<> class would define a method to perform an action on every item it contains, and through a "callback", you can define what that action is. Again, this is best implemented by defining an abstract class for the callbacks. See the discussion on "function objects" in C++ books.
When a callback is implemented as a separate object, you can easily configure it, at run time, by passing arguments to its constructors. Try _that_ with function pointers :)
>Every instance uses its own memory area for storing class variables
That would be _instance_ (not class) variables. The class variables are stored in an area of memory shared by all instances.
Reply