本次想分享下 嵌入式软件编程的第一个小技巧:回调函数的使用。
在设计程序中,合理的使用回调函数,可以降低层与层之间的耦合性。当下层需要传递数据给上层时,采用回调函数指针接口隔离变化。
调用方式有两种:1.在上层模块A调用下层模块B的函数中,直接调用回调函数C;2.使用注册的方式,当某个事件发生时,下层模块调用回调函数。
举个例子:
冒泡排序函数:
int compare_int(const int *e1,const int *e2)
{
return *e1 - *e2; //升序比较
}
int compare_int(const int *e1,const int *e2)
{
return *e2 - *e1; //降序比较
}
int compare_vstrcmp(const void *e1,const void *e2)
{
return strcmp(*(char **)e1,*(char **)e2); //字符串比较
}
//说明一下上面代码,strcmp传入的是地址,而且是const char*类型的,因此需要类型转换。然后传进来的e1是地址,因此转换的时候需要二级地址,即char **。
定义一个函数指针:
typedef int (* COMPARE)(const void *e1,const void *e2)
COMPARE compare;
//为了能兼容更多的参数类型,COMPARE指针的参数都设计为void*类型。
在设计一个字节交换函数(用于排序):
void byte_swap(void *pData1,void *pData2,size_t stSize)
{
unsigned char *pcData1 = pData1;
unsigned char *pcData2 = pData2;
unsigned char ucTemp;
while(stSize--)
{
ucTemp = *pcdata1; *pcdata1 = *pcdata2; *pcdata2 = uctemp;
pcdata1++;pcdata2++;
}
}
然后底层需要提供给上层接口函数,即可实现回调。
void bubbleSort(void *base,size_t nmemb,size_t size,COMPARE compare)
{
int hasSwap = 1;
for(size_t i = 1;hasSwap && i<nmemb;i++)
{
hasSwap = 0;
for(size_t j = 0;j < nmemb - 1; j++)
{
void *pThis = ((unsigned char*)base) + size * j;
void *pNext = ((unsigned char*)base) + size * (j+1);
if(compare(pThis,pNext)>0)
{
hasSwap = 1;
byte_swap(pThis,pNext,size);
}
}
}
}
接口函数bubbleSort传入的参数说明:base是数据的起始地址,nmemb是数据的总大小,size是数据中单个元素的大小,compare就是前面的回调函数。
这样就能很好的降低上层和底层的耦合性,当上层A想使用底层B时,只需要通过回调函数C,就可以使用。
例如:
int array[] = {39,33,54,26,896,15,36};
numArray = sizeof(array)/sizeof(array[0]);
bubbleSort(array,numArray,sizeof(array[0]),compare_int);
这样回调函数都属于上层模块,然后bubbleSort属于下层模块;下层模块不必知道需要调用上层模块的哪个函数,从而减少上下层之间的联系,这样上下层可以独立修改!!!。