16.VC(custom)-回调函数(callback function)

1. 回调函数(callback function)?

回调,就是两个程序A和C,程序A中含有函数b,程序C中含有函数d,当A要调用C的某个功能时,C需要反过来调用A中的函数b,而且是A不得不为C提供函数b,而C不知道A提供的b叫什么,有什么参数,所以C会规定b有什么参数,然后由A通过C中的函数d传入函数b的名字(也就函数d的一个参数和b的函数原型一致),这时b就是回调函数,而d就是注册函数.

举个例子

HHOOK SetWindowsHookEx(      
    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);

中参数HOOKPROC 就是相当于上述函数d的一个参数,它指定了回调函数的函数原型,比如在idHook为WH_MOUSE时,查看MSDN,可知"Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook procedure",所以MouseProc 就是它指定的回调函数的函数原型(HOOKPROC),继续查看MSDN,可知

LRESULT CALLBACK MouseProc(      

    int nCode,
    WPARAM wParam,
    LPARAM lParam
);

也就是对于拦截鼠标消息,程序A提供的回调函数b必须像MouseProc有一样的参数,同时通过注册函数SetWindowsHookEx传入b的名称,以告诉windows系统(也就是程序C)可以在得到鼠标消息时,反过来调用函数b进行处理.一般来说,A不会自己调用函数b,A提供函数b就是为了让C来调用的,而且是不得不提供.C提供函数d来规定函数b的原型,并传入它的名称.

 下面举个通俗的例子:

  我们不认识,但我知道你能帮我解决某个难题,所以我打电话向你请教问题,你一时想不出解决方法,我又不能拿着电话在那里一直等,于是我们约定:等你想出办法后再打电话给我,所以,我把电话号码告诉你,我就挂掉电话办其它事情去了。过了XX分钟,我的电话响了,你通过我提供的电话号码打回来告诉我应该如此这般处理。故事到此结束。

 这个例子说明了“异步+回调”的编程模式。(我打电话向你请教问题,我有你的电话,也就是能联系到你的函数),(你一时想不出解决方法,异步操作),(所以,我把电话号码告诉你,注册回调函数),(你通过我提供的电话号码打回来告诉我应该如此这般处理,我的电话号码应该和我告诉你的一致,这是回调函数必须符合接口规范),其中,你后来打电话告诉我结果便是一个“回调”过程。

2.什么时候使用回调?

一般来说,回调是一种嵌入,必须由调用者提供,不同的调用者可以提供不同的回调函数(只要参数符合接口规范)。

3.回调函数不能声明为成员函数?

#define CALLBACK    __stdcall

而在vc++中,所有类的成员函数在定义的时候都被隐式(implicit)定义为__thiscall参数传递方式,那么我们就来研究下__stdcall和__thiscall的区别

msdn对__stdcall的解释:

Microsoft Specific

The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype

msdn对__thiscall的解释:

所以类成员函数不能作为回调函数的主要原因在于类成员函数使用__thiscal参数传递方式,因此需要调用者(caller)通过ecx寄存器提供类对象的指针。而回调函数使用__stdcall参数传递方式,不具备这个特点,但是可以把回调函数声明为静态成员函数.


The __thiscall calling convention is used on member functions and is the default calling convention used by C++ member functions that do not use variable arguments. Under __thiscall, the callee cleans the stack, which is impossible for vararg functions. Arguments are pushed on the stack from right to left, with the this pointer being passed via register ECX, and not on the stack, on the x86 architecture.

关键句:with the this pointer being passed via register ECX, and not on the stack, on the x86 architecture

成员函数所在类的this指针被存入ecx寄存器(这个特性只针对Intel x86架构)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值