C++ Callback

原创 2011年01月09日 14:13:00

C++ Callback

2006/3/26 15:17:02
 

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.

相关文章推荐

C++ DLL C# CALLBACK

  • 2017年09月22日 15:38
  • 761KB
  • 下载

c++ callback

  • 2015年06月29日 01:54
  • 1.31MB
  • 下载

How to make a callback to C# from C/C++ code

注:个人觉得这篇技术文章很有价值,收藏下,本来想翻译一下,最近有点懒,过两天再说。 http://www.codeproject.com/Tips/318140/How-to-make-a-...

C++中回调(CallBack)的使用思路

  • 2010年08月24日 10:56
  • 74KB
  • 下载

C++回调函数(callback)的使用

什么是回调函数(callback)      模块A有一个函数foo,它向模块B传递foo的地址,然后在B里面发生某种事件(event)时,通过从A里面传递过来的foo的地址调用foo,通知A发生了...

binder 一个简单的c++服务的实现,与callback实现

研究了android binder 有两天了,感觉这是一个简单易用的东西,也许以后在非android的应用环境中也可以使用这种IPC方案,所以把一些学习记录下来,以将来备用. 今天主要是实现了一...

c++实现Callback机制

c++实现Callback机制          Callback是这样的一类对象(在这里不能简单的理解为"回调函数"了):你注册一个函数,以及调用它时的参数,希望在满足某个条件时,以这些注...

C++通过Callback向C#传递数据

现在比较流行C#与C++融合:C#做GUI,开发效率高,C++做运算,运行效率高,二者兼得。但是C++与C#必然存在数据交互,C#与C++dll的数据交互从来都是一个让人头疼的问题。...

C++回调(CallBack)方案

跟诸如Object Pascal和Ada等其它一些语言不同,C++语言并没有内在地提供一种将类的方法作为回调函数使用的方案。在C语言中,这种回调函数被称作算子(functor),在事件驱动类程序中普遍...
  • ax614
  • ax614
  • 2011年08月13日 11:58
  • 265

C/C++中Windows API 简单的(Callback)回调机制

C/C++中Windows API 简单的(Callback)回调机制
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Callback
举报原因:
原因补充:

(最多只允许输入30个字)