介绍下c(Brew Platform)语言中的CallBack(回调函数)机制
举Brew的IMedia的例子进行说明,详细如下:
用户程序(用户进程中运行)需要使用Brew系统服务(系统进程中运行)的IMedia接口,
先创建IMedia对象,然后调用IMEDIA_SetMediaParm,这个就不多说了。
然后就可以调用IMEDIA_RegisterNotify接口了,注意,该接口的第二个参数是个指针,用户需要定义该函数,然后把该函数的函数名作为参数。但定义该函数是一定要按照PFNMEDIANOTIFY的格式进行定义,具体可以查看AEEMedia.h文件中第201行。如果没有按照PFNMEDIANOTIFY进行定义,那么编译会有问题。
那么现在已经向IMedia注册CallBack函数了,接下来我们可以调用IMEDIA_PLAY接口进行播放多媒体文件了,在调用该函数后,IMEDIA_PLAY的返回值说明该函数是否调用成功,(因为在IMEDIA_PLAY函数中会有状态判断,这个不细说了)但是为啥还需要我们刚才注册的CallBack呢,原因是:
播放多媒体需要底层硬件的支持, 也就是说,IMEDIA会向硬件发出播放请求,如果硬件状态是允许播放(不允许同),那么IMedia模块就会调用用户注册的CallBack函数进行通知。
回调函数主要是运用在异步通信中。另外需要注意的是回调函数格式是在下层定义的。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
BREW协作式多任务特性,是通过C/C++的回调函数机制来实现的。其实所谓的回调函数是由系统调用用户的函数,由系统回调的函数,而非用户自行调用,这样用户就可以以根据需要动态改变系统的功能,但是要求用户设计的函数必须遵循系统的函数声明。而从技术上讲的所谓回调函数,其实就是函数指针,可以达到运行时动态调用函数的作用。
BREW中的回调函数除了使用在事件处理之外,定时器、复杂的数据加密算法和网络数据发送与接收等都使用回调函数技术,回调函数在基于事件处理的系统中还可以避免使用轮询技术导致应用程序陷入长时间的循环等待中。当把需要等待的事件或者是处理的任务作为回调函数注册到系统中,这样当系统接受到指定的消息或者是当系统处理完当前的任务,将会调用已经注册的回调函数。
在
BREW程序设计中,特别需要避免的是长时间的单一函数或者方法执行,或者是使用如下的技术:
while(1)
{
DoSomeThing();
}
这种技术在游戏设计中是经常采用的,一旦进入游戏,将进入用户自己的循环,只从系统得到需要的数据。但是在
BREW中,一旦陷入这种无限循环而无法及时响应系统消息,将会导致手持设备的强制性重新启动。
因此在
BREW中需要进行的周期性工作,一般是使用定时器来执行的,在设置定时器的时候,一般会同时初始化一个回调函数,这样在定时器结束后会调用这一个回调函数。
回调函数在
BREW中的另外一个作用就是对于复杂任务的分解执行,对于十分复杂的任务或者功能,可能执行时间较长,由于这将导致设备的重新启动,因此必须修改算法,把复杂算法分步执行,没有执行完的程序也需要立刻返回,并且把没有完成的工作注册为回调函数,等下次执行调用。
因此
BREW的协作式多任务由此可以产生,由于把复杂任务进行了分解,导致每次只执行一部分,并且各个任务都可以得到执行的机会,因此可以产生模拟的多任务效果。但是这里的多任务是协作的,需要由用户在程序设计中进行保证,必须及时出让占用的系统资源,这个是协作式与抢先式多任务的明显区别,虽然这样增加了用户进行程序设计的难度,但是却最大限度的节约了系统资源,最大限度地增加了系统的执行和运行效率。因此在嵌入式程序设计以及
BREW中被广泛采用。