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

来源:互联网 发布:js循环table tr 编辑:程序博客网 时间:2024/06/05 17:34
/*----------------------------------------------------------------------------Function Pointer: gui_start_timerDescription:      One shot timerInput Parameters: count    is the delay (Implementation dependent: Normally milliseconds)               callback is the function that is called when the timer expiresOutput Parameters:   noneReturns:       voidRemakrs:       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]);

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


0 0
原创粉丝点击