callback函数:举例说明C++回调函数(callback)的使用



什么是回调(callback)
模块A有foo它向模块B传递foo地址然后在B里面发生某种事件(event)时通过从A里面传递过来foo地址foo通知A发生了什么事情让A作出相应反应那么我们就把foo称为回调

例子:
回调个很有用也很重要概念当发生某种事件时系统或其他将会自动你定义回调在windows编程使用场合很多比如Hook回调:MouseProc,GetMsgProc以及EnumWindows,DrawState回调等等还有很多系统级回调过程本文不准备介绍这些和过程而是谈谈实现自己回调些经验
的所以产生使用回调这个想法现在使用VC和Delphi混合编程用VC写个DLL进行些时间比较长异步工作工作完成的后需要通知使用DLL应用:某些事件已经完成,请处理事件后续部分开始想过使用同步对象文件影射消息等实现DLL到应用通知后来突然想到可不可以在应用端先写等需要处理后续事宜时候在DLL里直接这个即可
于是就动手写了个回调原形在VC和Delphi里都进行了测试
:声明回调类型
vc版
typedef(WINAPI*PFCALLBACK)(Param1,Param2);
Delph版
PFCALLBACK=function(Param1:eger;Param2:eger):eger;stdcall;
实际上是声明了个返回值为,传入参数为两个指向指针
由于C和PASCAL编译器对参数入栈和返回处理有可能不类型用WINAPI(WINAPI宏展开就是__stdcall)或stdcall统修饰
2:声明回调原形
声明原形
vc版
WINAPICBFunc(Param1,Param2);
Delphi版
functionCBFunc(Param1,Param2:eger):eger;stdcall;
以上为全局如果要使用个类里作为回调原形把该类声明为静态即可 [Page]

3:回调
回调我把它放到了DLL里这是个很简单VC生成WIN32DLL.并使用DEF文件输出其名TestCallBack实现如下:
PFCALLBACKgCallBack=0;
voidWINAPITestCallBack(PFCALLBACKFunc)
{
(FuncNULL);
gCallBack=Func;
DWORDThreadID=0;
HANDLEhThread=CreateThread(NULL,NULL,Thread1,LPVOID(0),&ThreadID);
;
}
工作把传入PFCALLBACKFunc参数保存起来等待使用并且启动个线程声明了指针PFCALLBACKgCallBack保存传入地址
4:回调如何被使用:
TestCallBack启动了个线程作为演示线程人为进行了延时处理并且把线程运行过程打印在屏幕上.
本段线程代码也在DLL工程里实现
ULONGWINAPIThread1(LPVOIDParam)
{
TCHARBuffer[256];
HDChDC=GetDC(HWND_DESKTOP);


Step=1;
MSGMsg; [Page]
DWORDStartTick;
//个延时循环
for(;Step<200;Step)
{
StartTick=GetTickCount;
/*这段为线程交出部分运行时间以让系统处理其他事务*/
for(;GetTickCount-StartTick<10;)
{
(PeekMessage(&Msg,NULL,0,0,PM_NOREMOVE))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
} [Page]
/*把运行情况打印到桌面这是vcbear调试时最喜欢干事情*/
sprf(Buffer,\"Running%04d\",Step);
(hDC!=NULL)
TextOut(hDC,30,50,Buffer,strlen(Buffer));
}
/*延时段时间后回调*/
(*gCallback)(Step,1);
/*结束*/
::ReleaseDC(HWND_DESKTOP,hDC);
0;
}
5:万事具备
使用vc和Delphi各建立了个工程编写回调实现部分
VC版
WINAPICBFunc(Param1,Param2)
{
res=Param1+Param2;
TCHARBuffer[256]=\"\";
sprf(Buffer,\"callbackresult=%d\",res);


MessageBox(NULL,Buffer,\"Testing\",MB_OK);//演示回调
res; [Page]
}
Delphi版
functionCBFunc(Param1,Param2:eger):eger;
begin
result:=Param1+Param2;
TForm1.Edit1.Text:=tostr(result);//演示回调
end;

使用静态连接思路方法连接DLL里出口TestCallBack,在工程里添加Button(对于Delphi工程还需要在Form1上放个EditControl控件默认名为Edit1)
响应ButtonClick事件TestCallBack
TestCallBack(CBFunc)//参数CBFunc为回调地址
创建线程后立刻返回应用可以同时干别事情去了现在可以看到屏幕上不停显示表示dll里创建线程运行正常会的后线程延时部分结束结束vc应用弹出MessageBox,表示回调并显示根据Param1Param2运算结果DelphieditControl控件里文本则被改写成Param1Param2运算结果
可见使用回调编程模式可以根据区别需求传递区别回调地址或者定义各种回调原形(同时也需要改变使用回调参数和返回值约定)实现多种回调事件处理可以使控制灵活多变也是种高效率清晰模块的间耦合方式些异步或复杂系统里尤其有用--你可以在个模块(如DLL)里专心实现模块核心业务流程和技术功能外围扩展功能只给出个回调接口通过其他模块传递过来回调地址方式将后续处理无缝地交给另个模块随它按自定义方式处理
本文例子使用了在DLL里多线程延时后回调方式只是为了突出下回调效果其实只要是在本进程的内都可以随你高兴可以把地址传递来传递去当成回调使用
这样编程模式原理非常简单单:就是把也看成个指针个地址来没有什么别复杂东西仅仅是编程里个小窍门技巧至于回调模式究竟能为你带来多少好处就看你是否使用如何使用这种编程模式了 [Page]
另外解释:cdxiaogan
msdn上这么说:
有关指针知识
使用例子可以很好地介绍说明指针使用方法首先看Win32API中EnumWindows:
DeclareFunctionEnumWindowslib\"user32\"_
(ByVallpEnumFuncasLong,_
ByVallParamasLong)AsLong
EnumWindows是个枚举它能够列出系统中每个打开窗口句柄EnumWindows工作方式是重复地传递给它个参数(lpEnumFunc指针)每当EnumWindowsEnumWindows都传递个打开窗口句柄
在代码中EnumWindows时可以将个自定义作为第个参数传递给它用来处理系列例如可以编写将所有值添加到个列表框中将hWnd值转换为窗口名字以及其它任何操作!
为了表明传递参数是个自定义名称前面要加上AddressOf关键字第 2个参数可以是合适任何值例如如果要把MyProc作为参数可以按下面方式EnumWindows:
x=EnumWindows(AddressOfMyProc,5)
过程时指定自定义被称为回调回调(通常简称为“回调”)能够对过程提供数据执行指定操作
回调参数集必须具有规定形式这是由使用回调API决定有关需要什么参数如何它们请参阅API文档
回复人:zcchm
我谈下自己对回调点理解,不对地方请指教.
我刚开始接触回调时,也是团雾水.很多人解释这个问题时,总是拿API来举例子,本来菜鸟最惧怕就是API,^_^.回调跟API没有必然联系.
其实回调就是种利用指针进行过程.

为什么要用回调呢?比如我要写个子模块给你用,来接收远程发来命令.当我接收到命令后,需要主模块,来进行相应处理.但是我不知道你要用哪个来处理这个命令,我也不知道你主模块是什么.cpp或者.h,或者说,我根本不用关心你在主模块里如何处理它,也不应该关心用什么处理它......如何办?


使用回调.
我在我模块里先定义回调类型,以及回调指针.
typedefvoid(CALLBACK*cbkSendCmdToMain)(AnsiStringsCmd);
cbkSendCmdToMainSendCmdToMain;
这样SendCmdToMain就是个指向拥有个AnsiString形参,返回值为void指针.
这样,在我接收到命令时,就可以这个啦. [Page]
...
SendCmdToMain(sCommand);
...
但是这样还不够,我得给个接口(比如Init),让你在主模块里Init来注册这个回调.
在你主模块里,可能这样
voidCALLBACKYourSendCmdFun(AnsiStringsCmd);//声明
...
voidCALLBACKYourSendCmdFun(AnsiStringsCmd);//定义
{
ShowMessage(sCmd);
}
...
Init向我模块注册回调.可能这样:
Init(YourSendCmdFun,...);
这样,预期目就达到了.

需要注意点,回调般都要声明为全局.如果要在类里使用回调,前面需要加上,其实也相当于全局.
Tags:  vc回调函数 什么是回调函数 回调函数 callback函数

延伸阅读

最新评论

发表评论