/*----------------------------------------------------------------------------
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(x,y);
或者另外下面的写法:
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]);
因为函数指针的参数是一个指针函数。