从概念上,已经找了好多资料读。
可是,还是没从心里明白这个概念。
不妨就在这里说出来,希望得到指点。
回调函数,似乎好多人都推崇这个概念:    “使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。至于如何定义回调函数,跟具体使用的API函数有关,一般在帮助中有说明回调函数的参数和返回值等。C++中一般要求在回调函数前加CALLBACK,这主要是说明该函数的调用方式。DialogBox的回调函数实际上是个窗口过程,用来处理所有消息。”
    
     说实话,觉得这段话解释得不清楚。
     也有这样的解释:    “回调函数就相当于一个中断处理函数,由系统在符合你设定的条件时自动调用。为此,你需要做三件事:1,声明;2,定义;3,设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用。 
    声明和定义时应注意:回调函数由系统调用,所以可以认为它属于WINDOWS系统。不要把它当作你的某个类的成员函数。”    或者说回调函数不属于系统,只是把调用的入口条件(那个函数指针)交给了系统。
    
    这样解释不知道是否正确。
    那么,随之而来的我的疑问是这样的:
    程序的运行是靠消息驱动的,那么,回调函数和普通的,等待消息,得到消息便执行的函数有什么区别呢?而且,一个applacation的消息循环本身也是回调函数的条件判断部分吧?
    那么,一个消息循环的不断占用CPU,为什么不像我们做一个简单的死循环那样把cpu资源全部占用掉?
    这个机制是由系统,甚至硬件就带有的某项功能来实现的吧?
    说简单点,没有任何人的函数是由个人调用的。完成进程的执行,都是cpu。那么,都是系统调用的。回调函数和其他函数有区别,可是,应该不能说回调函数由系统调用而和其他函数不同。
    因为任何函数都是由系统满足了条件而去执行的呀。
    那么,回调函数和其他函数本质的区别究竟是什么呢?
    那么我猜想,cpu应该有某个单元是这样的功能:不断的扫描某个信号来确定是否有满足条件的指令然后压栈。而回调函数就是激活了这部分单元的功能来不断扫描是否满足了函数执行条件的。普通的函数却没有运用到cpu的这部分功能,所以,死循环才会占用好多的cpu,而callback却不会。
    但一切都是猜想。自己实在找不出比较合理的解释了。
    请指教。
    谢谢。

解决方案 »

  1.   

    回调函数没有你理解的那么深奥了,它不一定是系统调用的,你自已的程序也可以有自己的回调,我觉得上面的第一个解释说的比较清楚,只是太抽象了。举个例子吧,比如说在视频捕获的时候,有个帧回调函数,就是每当捕获到一帧数据的时候,就调用一下这个函数,这个函数的参数就是得到的视频数据缓冲区的指针,它大概的实现就是在捕获视频的那个函数(这个函数是sdk自己实现的)里,传入了你的回调函数的地址,然后他每次捕获视频数据的时候,在捕获视频的函数里就调用一下你定义的回调函数,并把视频数据缓冲区的指针作为回调函数的参数。而这个视频捕获函数的调用就是你在程序里面初始化的时候设置的,比如说每秒要捕获30帧数据,那就每秒调用30次这个视频捕获函数,同时也就调用了30次你的回调函数,在这个回调函数里面,你可以加入自己对视频数据的处理,比如压缩或者通过网络传送出去。不知道这样说有没有说懂。
      

  2.   

    我想我明白你的意思。还是举你所说的例子,我的疑问是:    为什么当我们设定了每秒钟30帧画面,那么,系统就会每隔1/30秒就会调用这个函数呢?
    系统是怎么知道1/30秒延时这个条件满足了,然后根据参数去调用函数的呢?
    而且在这期间,只要不满足条件,cpu应该处于闲置状态(消息循环看起来不占用cpu资源,或者说占得很少,但我坚信,windows运行环境下,cpu只能是部分闲置。而总体来讲,是不可能有一点点空闲的。)
        如果我们自己去写一个循环来判断是否满足延时条件(不用settimer这个api)
        那么,我们看见,cpu全部被占用在这个循环里面了。
        话说回来了:为什么消息循环和普通的循环不同,他可以不占用那么多的资源呢?
        这个问题有点愚蠢了。因为我自己也发现,实际上,这是由ms的系统内部封装好的功能,对外,似乎只留了api的用法。不知道这样说对不对。
        感谢楼上的回答得这么详细。谢谢
        goodluck
      

  3.   

    感觉callback就像是中断一样,可以随时在条件满足的情况下把cpu从当前的指令手中抢过来,不知道这个理解是否正确。
        我不明白的就是,怎样才能完成这样的功能呢?
        再用上面的数据采集为例子:
        捕捉数据的函数可以完成,但,捕捉数据成功了,这个消息,系统怎么就知道了呢?
        你说是一个循环来判断满足条件(可是,这个循环却和普通循环不同,它并不占用过多的cpu资源。为什么?)
        (回调函数似乎不是靠发送消息来通知系统的,或者说,发送了消息,而我却不知道。(对程序的开发者也是透明的吗?))
        谢谢
      

  4.   

    我想你没有看明白我说的意思,我说的每秒调用30次,不是直接调用30次回调函数,而是每秒进行30次视频采集,这个过程应该是调用了sdk自己定义的一个视频采集函数,在这个采集函数的最后是调用了你的回调函数,而这个采集函时是怎么实现每秒调用30次的,完全是由sdk自己去控制的,和回调函数没有关系,它可能是同timer主动的去采集,也可能是通过硬件中断来实现,这个我就不大明白了。就是这样的,假如说sdk自己定义了一个采集函数叫Capture(),然后你的帧回调函数叫做FrameCallback(LPVOID lpVoid),就是这样
    Capture(){
        
        进行数据采集,得到一个数据指针lpBmp
        FrameCallback(lpBmp);
    }
    然后,sdk通过一定的机制会每秒调用30次Capture()函数。
      

  5.   

    哦,也许我是没有明白你的意思。
        看看我现在的理解是否对呢?
        作为参数传入函数内,然后执行,这是函数指针的应用之一。
        而callback函数本身其实并没有太多的其他什么特性,只不过是必须是静态的或者全局的
        是否可以这样理解呢?(因为也有资料上说 callback 本身在被编译时,就是farpasical的什么调用方式,我不太了解了)
        再比如,普通的函数,其实一样可以通过函数指针的传递来实现这样的功能,但,却不是静态的或者全局的函数?是这样的吗?
        那么,现在,问题分成两个了
        1 被定义为callback的函数,就本身而言,似乎和其他函数功能没有什么区别,只是调用方法特殊一些,编译后在内存段的地址也特殊一些,不知是否正确。
        2 不管是sdk也好,mfc,甚至api也好,他们究竟怎么实现的实时响应外部的突发事件,应该是对应用程序开发者也是透明的吧?比如:一个关于定时响应的函数,我可以用settimer来做每隔一段时间就执行我们自定义的内容,但是,却不知道系统是如何得到这样的消息——时间到了,该执行应用程序的那个函数了。
        是这样的吗?
        非常感谢wkgenius()的热心帮忙和解释。