`
starnc
  • 浏览: 142060 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

c#委托相当于c++的回调函数(函数指针)

    博客分类:
  • .NET
阅读更多

       回调函数,就是由你自己写的。你需要调用另外一个函数,而这个函数的其中一个参数,就是你的这个回调函数名。这样,系统在必要的时候,就会调用你写的回调函数,这样你就可以在回调函数里完成你要做的事。 

 

 typedef   int   (__stdcall   *PFunc)(int,   int);   
    
  int   __stdcall   Max(int   a,   int   b)   
  {   
  return   a   >   b   ?   a   :   b;   
  }   
    
  int   __stdcall   Test(PFunc   func,   int   a,   int   b)   
  {   
    
  return   func(a,   b);   
  }   
    
  void   main()   
  {   
  cout   <<   Test(Max,   1,   30)   <<   endl;   
  }   

  

  就是:   不是你直接调用的函数   而是   系统/或者其他地方调用的  
  比如   如果是API需要传入回调函数   那么就是API里面调用这个回调函数  
  如果是你自己的函数调用   。。那么同样了   比如 上面的代码。

=======================================================================

在C#中,委托的作用是这样描述的:委托就像一个函数的指针,在程序运行时可以使用它们来调用不同的函数。这个其实和你委托同事完成 JS代码一样。如果有两位同事可以做这件事情,他们只要做的结果能够满足你的需求(就像一个接口),尽管他们做的过程不一样,并且作出的效果也不一样,但是,能够达到你的要求就可以了。
 
=======================================================================

 

软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础。  
  对于不同类型的语言(如结构化语言和对象语言)、平台(Win32、JDK)或构架(CORBA、DCOM、WebService),客户和服务的交互除了同步方式以外,都需要具备一定的异步通知机制,让服务方(或接口提供方)在某些情况下能够主动通知客户,而回调是实现异步的一个最简捷的途径。  
   
  对于一般的结构化语言,可以通过回调函数来实现回调。回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。  
   
  在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类成为回调类,回调类的对象成为回调对象。对于象C++或Object   Pascal这些兼容了过程特性的对象语言,不仅提供了回调对象、回调方法等特性,也能兼容过程语言的回调函数机制。  
   
  Windows平台的消息机制也可以看作是回调的一种应用,我们通过系统提供的接口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。由于Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个特例。  
   
  对于分布式组件代理体系CORBA,异步处理有多种方式,如回调、事件服务、通知服务等。事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。对一些简单的异步处理过程,我们可以通过回调机制来实现。  
   
  下面我们集中比较具有代表性的语言(C、Object   Pascal)和架构(CORBA)来分析回调的实现方式、具体作用等。  
   
  2   过程语言中的回调(C)  
   
   
  2.1   函数指针  
  回调在C语言中是通过函数指针来实现的,通过将回调函数的地址传给被调函数从而实现回调。因此,要实现回调,必须首先定义函数指针,请看下面的例子:  
   
   
  void   Func(char   *s);//   函数原型  
  void   (*pFunc)   (char   *);//函数指针  
   
   
   
  可以看出,函数的定义和函数指针的定义非常类似。  
   
  一般的化,为了简化函数指针类型的变量定义,提高程序的可读性,我们需要把函数指针类型自定义一下。  
   
   
  typedef   void(*pcb)(char   *);  
   
   
   
  回调函数可以象普通函数一样被程序调用,但是只有它被当作参数传递给被调函数时才能称作回调函数。  
   
  被调函数的例子:  
   
   
  void   GetCallBack(pcb   callback)  
  {  
  /*do   something*/  
  }  
  用户在调用上面的函数时,需要自己实现一个pcb类型的回调函数:  
  void   fCallback(char   *s)  
  {  
  /*   do   something   */  
  }  
  然后,就可以直接把fCallback当作一个变量传递给GetCallBack,  
  GetCallBack(fCallback);  
   
   
   
  如果赋了不同的值给该参数,那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。  
   
  2.2   参数传递规则  
  到目前为止,我们只讨论了函数指针及回调而没有去注意ANSI   C/C++的编译器规范。许多编译器有几种调用规范。如在Visual   C++中,可以在函数类型前加_cdecl,_stdcall或者_pascal来表示其调用规范(默认为_cdecl)。C++   Builder也支持_fastcall调用规范。调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。  
   
  将调用规范看成是函数类型的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:  
   
   
  //   被调用函数是以int为参数,以int为返回值  
  __stdcall   int   callee(int);  
   
  //   调用函数以函数指针为参数  
  void   caller(   __cdecl   int(*ptr)(int));  
   
  //   在p中企图存储被调用函数地址的非法操作  
  __cdecl   int(*p)(int)   =   callee;   //   出错  
   
   
   
  指针p和callee()的类型不兼容,因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针p,尽管两者有相同的返回值和参数列  
   
  2.3   应用举例  
  C语言的标准库函数中很多地方就采用了回调函数来让用户定制处理过程。如常用的快速排序函数、二分搜索函数等。  
   
  快速排序函数原型:  
   
   
  void   qsort(void   *base,   size_t   nelem,   size_t   width,   int   (_USERENTRY   *fcmp)(const   void   *,   const   void   *));  
  二分搜索函数原型:  
  void   *bsearch(const   void   *key,   const   void   *base,   size_t   nelem,  
  size_t   width,   int   (_USERENTRY   *fcmp)(const   void   *,   const   void   *));  
   
   
   
  其中fcmp就是一个回调函数的变量。  
   
  下面给出一个具体的例子:  
   
   
  #include   <stdio.h>  
  #include   <stdlib.h>  
   
  int   sort_function(   const   void   *a,   const   void   *b);  
  int   list[5]   =   {   54,   21,   11,   67,   22   };  
   
  int   main(void)  
  {  
  int   x;  
   
  qsort((void   *)list,   5,   sizeof(list[0]),   sort_function);  
  for   (x   =   0;   x   <   5;   x++)  
  printf("%i\n",   list[x]);  
  return   0;  
  }  
   
  int   sort_function(   const   void   *a,   const   void   *b)  
  {  
  return   *(int*)a-*(int*)b;  
  }  
   
   
   
  2.4   面向对象语言中的回调(Delphi)  
   
  Dephi与C++一样,为了保持与过程语言Pascal的兼容性,它在引入面向对象机制的同时,保留了以前的结构化特性。因此,对回调的实现,也有两种截然不同的模式,一种是结构化的函数回调模式,一种是面向对象的接口模式。  

 

=======================================================================

 

http://dev.csdn.net/develop/article/20/20778.shtm  
  我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理、用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函数)有何不同呢?这里结合自己的使用经历做一个简单的介绍。  
   
  使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。C++中一般要求在回调函数前加CALLBACK(相当于FAR   PASCAL),这主要是说明该函数的调用方式。  
   
  至于钩子函数,只是回调函数的一个特例。习惯上把与SetWindowsHookEx函数一起使用的回调函数称为钩子函数。也有人把利用VirtualQueryEx安装的函数称为钩子函数,不过这种叫法不太流行。  
   
  也可以这样,更容易理解:回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事:  
   
  1.   声明;  
   
  2.   定义;  
   
  3.   设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用。  
   
  声明和定义时应注意:回调函数由系统调用,所以可以认为它属于WINDOWS系统,不要把它当作你的某个类的成员函数  
   
   
   
   
  http://www.china-askpro.com/msg25/qa03.shtml  
   
  使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。C++中一般要求在回调函数前加CALLBACK,这主要是说明该函数的调用方式。DialogBox的回调函数实际上是个窗口过程,用来处理所有消息。其定义为:  
  BOOL   CALLBACK   DialogProc(  
   
  HWND   hwndDlg,   //   handle   of   dialog   box  
  UINT   uMsg,   //   message  
  WPARAM   wParam,   //   first   message   parameter  
  LPARAM   lParam   //   second   message   parameter  
  );  
  在Win32   API中有详细说明。一般使用C++   Builder或MFC的往往没有使用SDK编程的经验,建议找一些SDK编程的书看一下,否则很难理解如何使用窗口过程。  
  至于钩子函数,只是回调函数的一个特例。习惯上把与SetWindowsHookEx函数一起使用的回调函数称为钩子函数。也有人把利用VirtualQueryEx安装的函数称为钩子函数,不过这种叫法不太流行。  
   
   
  Top  
  回复人:useresu(俗人)(努力做翻译ing)   (   一星(中级))   信誉:100   2005-6-8   16:50:36   得分:10  
  ?    
   
  回调一般是在函数参数中声明一个函数指针,随其他函数参数一起传入(参数一般是指针类型传址),  
  该指针类型为一个CALLBACK的函数,  
  在相应的回调函数中实现对参数的设置,  
   
  Top  
  回复人:sunman1982(冥王星)   (   三级(初级))   信誉:100   2005-6-8   17:04:58   得分:0  
  ?    
   
  chinunix   kunx   right?  
  Top  
  回复人:laolaoliu2002(老刘)   (   一级(初级))   信誉:100   2005-6-8   17:37:13   得分:0  
  ?    
   
  使用回调函数实际上就是在调用某个函数(通常是   API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。C++中一般要求在回调函数前加CALLBACK,这主要是说明该函数的调用方式。DialogBox的回调函数实际上是个窗口过程,用来处理所有消息。其定义为:  
  BOOL   CALLBACK   DialogProc(  
   
  HWND   hwndDlg,   //   handle   of   dialog   box  
  UINT   uMsg,   //   message  
  WPARAM   wParam,   //   first   message   parameter  
  LPARAM   lParam   //   second   message   parameter  
  );  
  在Win32   API中有详细说明。一般使用C++   Builder或MFC的往往没有使用SDK编程的经验,建议找一些SDK编程的书看一下,否则很难理解如何使用窗口过程。  
  至于钩子函数,只是回调函数的一个特例。习惯上把与SetWindowsHookEx函数一起使用的回调函数称为钩子函数。也有人把利用VirtualQueryEx安装的函数称为钩子函数,不过这种叫法不太流行。

 

=====================================================================

均为复制,并非原创,但能讲清楚问题

分享到:
评论

相关推荐

    C# 调用C++DLL(函数参数包含指针)

    C#调用C++DLL,C++DLL中的函数参数包含指针。 绝对可用。

    C#中的委托类似C++中的函数的指针,功能强大,灵活

    在C#中,为了提供类似C++中函数指针的功能,微软提出了委托和事件的概念。这里有一个很奇怪的事情,那就是当牵涉到指针是,对于初学者而言,似乎很费解。鄙人对于C#中的委托和事件有一些见解,希望对那些要了解委托...

    C# 调用c++ 库 参数为指针类型导出函数

    c# Csharp调用 c++库 参数为导入和导出指针两种 包含C++ DLL源码 如fun(cont char* A,char*B) A为输入参数,B为输出参数-C# CSharp call C++ DLL lib dll function param use export and import eg: fun(cont char*...

    详解C#中通过委托来实现回调函数功能的方法

    委托(delegate)是一种可以把引用存储为函数的类型,这类似于c++中的函数指针。 回调函数 c++中的回调函数,就是用函数指针来实现的。类似的,c#中用委托,来实现回调函数的功能。 回调函数为什么被称为回调函数?...

    C++ 使用STL和函数指针 实现的委托

    C++模拟实现的类似于C#的委托。 使用STL封装类名称的变化,使用函数指针封装函数名称的变化。 在Visual C++ 6.0下测试通过。 使用的时候只需要关注IFunctor和IDelegate两个接口即可。

    成员函数指针与高性能的C++委托

    成员函数指针与高性能的C++委托着重描述C++中如何实现其他面向对象语言如C#,JAVE中的委托功能

    调用示例.rar_C#调用c++ dll_C#调用函数指针_C#调用结构体_结构体_调用C dll

    C#调用C++ dll, 包括结构体, 数组, 函数指针, 字符串等等

    C#委托所蕴含的函数指针概念详细解析

    2、回调函数callback使用的技术就是函数指针: 回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。为此,你需要做三件事: 1). 声明; 2). 定义; 3). 设置触发条件,就是在你的函数中把你的...

    c#委托与事件的关系

    c#用委托来实现事件通知机制。委托相当与c++函数指针。整个过程涉及一个呼叫者,一个被呼叫者,还有就是这个委托。

    C#中byte数组和c++结构体的转换

    在写C#TCP通信程序时,发送数据时,只能发送byte数组,处理起来比较麻烦不说,如果是和c++等写的程序通信的话,很多的都是传送结构体,在VC6.0中可以很方便的把...C#调用c++dll时也可以使用此函数来转换结构体或指针。

    C#高级编程_委托和事件

    回调函数实际上是方法调用的指针,也称为函数指针,是一个非常强大的 编程特性。.NET 以委托的形式实现了函数指针的概念。它们的特殊之处是,与C 函数指针不同,.NET 委托是类型安全的。这说明,C中的函数指针只不过...

    C#调用CDLL带指针参数的函数

    C#调用CDLL带指针参数的函数的实例.

    委托实例,简单易懂

    介绍完生活中委托是个什么后,现在就看看C#中的委托怎样和生活中的对象联系起来的,C#中的委托相当于C++中的函数指针(如果之前学过C++就知道函数指针是个什么概念的了),函数指针是用指针获取一个函数的入口地址,...

    C++实现C#事件机制

    C++ 模拟 C# 事件 函数指针 尾随参数

    CallBackInteropTest

    因需要,需要封装一个C++网络库到C#环境使用,而C++网络库是使用的事件的方式,也就是说,发生网络事件时,C++网络库发出事件通知,而真正的处理...关键词:C# C++ 互操作 封送 封送回调函数 封送函数指针 C#C++回调

    C++中实现委托(delegate)

    网上有很多关于C++ delegate机制的文章,但都讲的是函数指针的内容,上周就C++中实现C#的delegate机制的问题研究了好几天,查看了很多相关资料,才解决了问题,现将我写的C++ delegate测试程序贴出来,希望能帮到有...

    基于C#调用c++Dll结构体数组指针的问题详解

    下面小编就为大家分享一篇基于C#调用c++Dll结构体数组指针的问题详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    C#调用C++编写的DLL函数各种参数传递

    C#调用C++编写的DLL函数各种参数传递

    才C#于C++的差别

    C#于C++的差别 下表包含 C# 和本机 C++(它不使用 /clr)之间的重要比较信息。如果您是一位 C++ 程序员,此表将为您提供这两种语言的最重要差异。 1、继承:在 C++ 中,类和结构实际上是相同的,而在 C# 中,它们很...

    委托给了C#操作函数的灵活性

    委托给了C#操作函数的灵活性,我们可使用委托像操作变量一样来操作函数,其实这个功能并不是C#的首创,早在C++时代就有函数指针这一说法,而在我看来委托就是C#的函数指针,首先先简要的介绍一下委托的基本知识

Global site tag (gtag.js) - Google Analytics