本文共 5226 字,大约阅读时间需要 17 分钟。
回调函数是异步返回的,满足某种条件后系统将调用此函数,以便于程序进行处理。
其实有点类似于消息,但是比消息好用,因为消息可能被中途截获或篡改,而回调函数没办法截获,比较安全。
同时,消息一旦多了之后,时序很容易发生问题,用回调函数要好一些
回调函数必有的三要素:
(1)函数指针的定义;(类似定义了一种类型 比如int char等)
(2)函数指针的函数赋予;(这个函数指针指向了谁,谁就是回调后要执行的动作)
(3)函数指针的参数输入:(此时开始执行相应的动作)
A
typedef void (*PRIME_NOTIRY_CB)(unsigned char evt, unsigned char * dat); /首先有定义(*PRIME_NOTIRY_CB)
这样PRIME_NOTIRY_CB就是一种类型了,类似(int,char等)
可以用它PRIME_NOTIRY_CB来定义同样的变量比如下面
PRIME_NOTIRY_CB pNotifierCb; //那么pNotifierCb也是指向此类函数的指针 void (unsigned char evt, unsigned char * dat);
prime_init(prime_notify_callback);
int prime_init(PRIME_NOTIRY_CB notifierFunc)/// { HAL_Init(NULL); // must be after HAL_Init(NULL)! UTIL_Lock(); memset(&g_tVar, 0, sizeof(TPrimeIF)); g_tVar.pNotifierCb = notifierFunc;/给指针函数赋予函数,在这里就把prime_notify_callback赋予了pNotifierCb
/也就是说pNotifierCb已经指向了一个函数,下次在pNotifierCb填入输入参数后即可执行指向的函数 prime_notify_callback, TIMER_SetDelay_ms(&g_tVar.tChkStateTm, PRIME_CHK_STATE_MAX_WAIT); TIMER_Start(&g_tVar.tChkStateTm); UTIL_Unlock(); return 0; }
static void prime_notify_callback(unsigned char evt, unsigned char * buf) { int node_process=-1; int addr_buff; unsigned char * eui49_p; char log_text[256]; struct tm eventTm; time_t now = time(NULL); mlocaltime(now, &eventTm); tkinfo.task_live[1]=1; //printf("**************************有上线的或掉线的回调******************************\r\n"); if (evt == PRIME_IF_EVT_JOIN_IND) { printf("**************************有电表主动上线***************\r\n"); for(int i=0;i<32;i++) { { printf("%02x ",buf[i]); } }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
if (g_tVar.pNotifierCb != NULL) { TempBuf[0] = (TU8)((ST7590_Status.LastDA >> 8) & 0xFF); TempBuf[1] = (TU8)((ST7590_Status.LastDA) & 0xFF); g_tVar.pNotifierCb(PRIME_IF_EVT_LEAVE_IND, TempBuf);//在pNotifierCb填入输入参数后即执行指向的函数//Prime_notify_callback(PRIME_IF_EVT_LEAVE_IND, TempBuf), }
B 简易的回调函数
//协议回调函数:>0 成功;<0 失败 typedef int (*prot_callback)(void* args); //定义prot_callback函数指针可以执行此类的函数 int (void* args);
prot_callback collection_callback =NULL; // 指针先指向空; collection_callback 是全局函数指针
set_collection_task_callback((prot_callback)add_system_timer_task);
//任务下装回调 void set_collection_task_callback(prot_callback callback) ///通过此句就初始化了函数指针collection_callback 指向了add_system_timer_task { collection_callback =callback; }
........................................
后续就等如果后面加了相应的参数了,就相当于执行add_system_timer_task
if(collection_callback !=NULL)collection_callback(&task);
void add_system_timer_task(COLLECTION_TASK_PTR ptask ) { if(ptask ==NULL) return ; TI ti =ptask->freq; TimerConfig timeconfig ={.curtime =time(0),0,ti.interval,ti.unit,.type =ptask->task_type}; time_t t =datetime2time(&ptask->start_time); uint sec =ti2second(ptask->delay_ti); t+=sec; //存在延时 localtime_user(&t,&timeconfig.basetime); log_print(TASK,"add task to system timer, taskno =%d ,ti ={unit =%d,interval =%d},delay_ti ={unit =%d,interval =%d} taskpriority =%d \n", ptask->task_no,ti.unit,ti.interval,ptask->delay_ti.unit,ptask->delay_ti.interval,ptask->task_priority); SysAddRTimer(ptask->task_no,&timeconfig, get_timer_proc(ti.unit), ptask->task_no); }
C 较为复杂的
*获取类包含的数据项
*/
typedef const OOPItem* (*oopitem_list)(byte apdu_flag); //在这里定义了oopitem_list,他是typedef const OOPItem* (byte apdu_flag)此类型函数的指针,返回的是OOPItem* 指针类型。
struct oopitem { ushort oi; ushort prop; uint cfg; oopitem_func opf; }; typedef struct { ClassID id; byte OIA[10]; oopitem_list item_list;/前面已经定义过oopitem_list ,这里直接用(可以看做 char int等等只是一个类型) param_addr_funcparam_addr_func; apdu_operation request; apdu_operationresponse; }ClassOperation;
OOPItem* getOOPItem(byte apdu_flag,uint oad) { OOPItem *pitem =NULL; const ClassOperation* p =get_class_operation(oad>>16);///比如取出的采集监控类 P指向了class_oprs[] 数组的这行
/{collection_id,{0x60},collection_item_list,get_collection_param_addr}, if(p ==NULL) return NULL; pitem = (OOPItem*)(p->item_list(apdu_flag));重点:在此就(p->item_list )就相当于函数指针了, 指向了collection_item_list,相当于执行collection_item_list, 后面如果如果有添加相应的输入参数,就开始执行指向的函数collection_item_list
其实这一句话隐含了一个操作就是 p->item_list=collection_item_list;因为参数传递
while (pitem != NULL && pitem->oi != END_LIST_ITEM) { uint o =OAD(pitem->oi,pitem->prop); if(oad == o) return pitem; else if(((oad>>8) ==(o>>8)) && ((o&0xff) ==0xff)) { return pitem; } pitem++; } return NULL; }
const OOPItem* collection_item_list(byte apdu_flag) { if(apdu_flag ==ACTION_APDU) return oop_oprs; else return oopitems; }
const static ClassOperation class_oprs[] = { //数据 {data_id, {0x20,0x21,0x22}, tmnldata_item_list,}, //事件 {event_id, {0x30,0x31,0x32,0x33}, event_item_list,NULL,event_operator}, //参数 { param_id, {0x40,0x41,0x042},param_item_list,get_tmnl_param_addr }, //设备 {device_id, {0x43}, device_item_list,get_device_param_addr}, //应用链接 {connect_id, {0x44}, connect_item_list, get_connect_param_addr}, //采集监控接口类 {collection_id,{0x60},collection_item_list,get_collection_param_addr}, //ESAM接口类 {esam_id, {0xf1}, esam_item_list,get_esam_param_addr}, //总加组类 {total_group_id,{0x23},total_item_list}, //脉冲类 {pulse_id, {0x24}, pulse_item_list}, //控制类 {control_id, {0x80,0x81}, control_item_list}, //以太网通信接口类(包含GPRS) {network_id, {0x45}, class26_network_item_list}, //输入输出接口 {io_id, {0xf2}, io_item_list}, //冻结接口 {freeze_id, {0x50}, freeze_item_list}, //文件传输 { file_id, {0xf0 }, file_item_list }, };
转载地址:http://trhxi.baihongyu.com/