从gui_start_timer函数来看函数指针、指针函数、回调函数

/*----------------------------------------------------------------------------
Function Pointer: gui_start_timer
Description:      One shot timer
Input Parameters: count    is the delay (Implementation dependent: Normally milliseconds)
               callback is the function that is called when the timer expires
Output Parameters:   none
Returns:       void
Remakrs:       NOTE: DO NOT USE UI TIMER IN CRITICAL CASES
               UI timer will be suspended when LCD backlight is turned off.
----------------------------------------------------------------------------*/

void (*gui_start_timer) (S32 count, void (*callback) (void)) = NULL;
<pre name="code" class="cpp">void setup_UI_wrappers(void)
{
    gui_start_timer = UI_start_timer;

}
 
 
typedef void (*gui_timer_funcptr_type)(void *);
static gui_timer_funcptr_type UI_timer_callbacks[MAX_UI_TIMERS];
static U8 UI_timer_ID_flags[MAX_UI_TIMERS]; /* 0 means timer is available */
static void *UI_timer_args[MAX_UI_TIMERS];
 
static void UI_start_timer(S32 count, FuncPtr callback)
{
    UI_start_timer_ex(count, (gui_timer_funcptr_type)<span style="color:#ff0000;">callback</span>, NULL);
}

static void UI_start_timer_ex(S32 count, gui_timer_funcptr_type callback, void *arg)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    S16 i;
    U8 all_timers_used = 1;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/    
    /* check if this function has already been hooked. If yes, remove it */
    for (i = 0; i < MAX_UI_TIMERS; i++)
    {
        if ((UI_timer_ID_flags[i]) && (UI_timer_callbacks[i] == callback))
        {
            HW_StopTimer(i);
            UI_timer_callbacks[i] = (gui_timer_funcptr_type)UI_dummy_function;
            UI_timer_ID_flags[i] = 0;
        }
    }


    /* Check for free timer */
    for (i = 0; i < MAX_UI_TIMERS; i++)
    {
        if (UI_timer_ID_flags[i] == 0)
        {
            all_timers_used = 0;
            break;
        }
    }
    /* If all timers are used, return   */
    if (all_timers_used)
    {
        return;
    }

    /* Hook the callback function and start the OS timer  */
    UI_timer_callbacks[i] = callback;
    UI_timer_args[i] = arg;
    HW_StartTimer((U16)(UI_TIMER_ID_BASE + i), (U32)count, UI_timer_callback, (void*)i);

    /* Set the timer to busy   */
    UI_timer_ID_flags[i] = 1;
}
void UI_timer_callback(void *arg)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    S32 timer_id = (S32)arg;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    HW_StopTimer(timer_id);
    UI_timer_ID_flags[timer_id] = 0;

    mmi_frm_dss_defer_dump_string(MMI_FALSE);
	if(UI_timer_callbacks[timer_id])
	{
		UI_timer_callbacks[timer_id](UI_timer_args[timer_id]);
	}

    mmi_frm_dss_defer_dump_string(MMI_TRUE);
}


void (*gui_start_timer) (S32 count, void (*callback) (void)) = NULL;
这是一个函数指针。

判断是指针函数还是函数指针重点落在后面的两个字上。

指针函数本质上还是函数,只是函数的返回值为某种类型的指针。例:

int *f(xy);

或者另外下面的写法:

int* f(x,y);

(int*) f(x,y);

函数指针的本质是指针,只是它是一个指向函数的指针变量。

int (*f)(x,y);

void (*f)(x,y);

由UI_timer_callback()函数里面下面这一句:

if(UI_timer_callbacks[timer_id])
{
UI_timer_callbacks[timer_id](UI_timer_args[timer_id]);
}

我们可以知道函数指针的调用方式。

例如:

 void (*fptr)();

把函数的地址赋值给函数指针,可以采用下面两种形式:
        fptr=&Function;
        fptr=Function;

取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
    
可以采用如下两种方式来通过指针调用函数:
        x=(*fptr)();
        x=fptr();

以上例如为网上引用来的。建议程序员调用函数指针的时候都采用第一种方式,这样增加代码的易读性。


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


函数指针和指针函数弄明白后,通过gui_start_timer这个例子,我们还可以看到回调函数的实现方式。

UI_timer_callbacks其实是UI_start_timer()函数中回调函数参数的最终实现。

所以回调函数其实就是以函数指针的形式指针调用函数来实现的

在网上搜到一个很好的案例:

一般需要定义一个函数指针类型

1
typedef  int  (*function_pointer_t) (  int  arg1,  int  arg2 );

然后,定义函数指针变量

1
function_pointer_t fp_invoker = 0;

函数指针可以动态改变内容,改变调用对象,假设有两个函数

1
2
3
4
5
6
7
8
int  function_sum(  int  arg1,  int  arg2 )
{
     return  arg1+arg2;
}
int  function_sub(  int  arg1,  int  arg2 )
{
     return  arg1-arg2;
}

注意到两个函数的原型与函数指针类型是一致的。以下是调用

1
2
3
4
fp_invoker = function_sum;  // 直接用函数名赋值即可
fp_invoker(1,2);            // 调用时,可以认为函数指针便是函数名,此时调用加法
fp_invoker = function_sub;  // 同理,切换到减法
fp_invoker(1,2);            // 调用减法

以上都是直观的用法,通常函数指针用于回调,即下层函数先将函数指针内容保存起来,处理结束后,再调用。此时要注意首先检查函数指针内容是否为空。

1
2
3
if ( fp_invoker ){
     fp_invoker( arg1, arg2 );
}

mtk的这个调用稍微复杂一点:

UI_timer_callbacks[timer_id](UI_timer_args[timer_id]);

因为函数指针的参数是一个指针函数。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值