• 正文
    • 1、前言
    • 2、函數(shù)調(diào)用方式
    • 3、什么場(chǎng)景使用
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

嵌入式軟件架構(gòu)設(shè)計(jì)-函數(shù)調(diào)用

04/03 13:01
181
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

1、前言

函數(shù)調(diào)用很好理解,即使剛學(xué)沒(méi)多久的朋友也知道函數(shù)調(diào)用是怎么實(shí)現(xiàn)的,即調(diào)用一個(gè)已經(jīng)封裝好的函數(shù),實(shí)現(xiàn)某個(gè)特定的功能。

把一個(gè)或者多個(gè)功能通過(guò)函數(shù)的方式封裝起來(lái),對(duì)外只提供一個(gè)簡(jiǎn)單的函數(shù)接口,然后在其他地方調(diào)用即可

2、函數(shù)調(diào)用方式

函數(shù)調(diào)用難道還能怎么調(diào)用?不就封裝好直接調(diào)用嗎???

函數(shù)調(diào)用方式分為兩種:直接調(diào)用和間接調(diào)用

直接調(diào)用

直接調(diào)用就是我們平常使用的方式,下面的方式就屬于直接調(diào)用了。

int?SumFun(int?a,?int?b)
{
return?a?+?b;
}

int?main()
{
//?直接調(diào)用定義好的函數(shù)
int?sum?=?SumFun(5,?6);
printf("sum=%d",?sum);
return?0;
}

間接調(diào)用

間接調(diào)用在初學(xué)時(shí)很難使用到,這是通過(guò)函數(shù)指針的方式實(shí)現(xiàn)的。

函數(shù)指針本質(zhì)是一個(gè)指針變量,是一個(gè)指向函數(shù)的指針(函數(shù)本身也是有地址的,指向的是函數(shù)入口);

而指針函數(shù)本質(zhì)是一個(gè)函數(shù),其返回值為指針。

函數(shù)指針的用法如下:

typedef?int?(*FunctionCB)(int,?int);

int?SumFun(int?a,?int?b)
{
return?a?+?b;
}

int?main()
{
//?將定義好的函數(shù)賦值給函數(shù)指針
FunctionCB?pfnSum?=?SumFun;

//?通過(guò)函數(shù)指針間接調(diào)用
int?sum?=?pfnSum(5,?6);
printf("sum=%d",?sum);
return?0;
}

3、什么場(chǎng)景使用

函數(shù)指針在軟件架構(gòu)分層設(shè)計(jì)中十分重要,因?yàn)榉謱釉O(shè)計(jì)中有一個(gè)設(shè)計(jì)原則,那就是下層函數(shù)不能直接調(diào)用上層函數(shù),那么可以通過(guò)函數(shù)指針的方式實(shí)現(xiàn);一般稱上層通過(guò)函數(shù)指針賦值給下層的函數(shù)為回調(diào)函數(shù)。

什么情況會(huì)存在需要下層程序需要調(diào)用上層程序的呢?

比如串口數(shù)據(jù)接收,雖然可以通過(guò)查詢的方式接收,但是遠(yuǎn)不及通過(guò)串口中斷的方式接收及時(shí),當(dāng)接收完成時(shí),需要立即通知上層讀取數(shù)據(jù)進(jìn)行處理,而不是等待上層程序查詢讀取。

如何實(shí)現(xiàn)呢?

比如硬件抽象層/驅(qū)動(dòng)層中的串口模塊實(shí)現(xiàn)函數(shù)

/*************?UART.c?文件?****************/
static?UartRecvCB?sg_pfnUartRecv;

//?設(shè)置數(shù)據(jù)幀接收處理回調(diào)函數(shù)
void?UART_SetRecvCallback(UartRecvCB?pfnUartRecv)
{
sg_pfnUartRecv?=?pfnUartRecv;
}

void?UART_Task(void)
{
if?(RecvEnd)
{
//?數(shù)據(jù)一幀接收完成立即調(diào)用
if?(sg_pfnUartRecv?!=?NULL)
{
sg_pfnUartRecv(UartRecvBuf,?UartRecvLength);
}
}
}

/*************?UART.h?文件?****************/
typedef?void?(*UartRecvCB)(const?char?*,?int);

extern?void?UART_SetRecvCallback(UartRecvCB?pfnUartRecv);
extern?void?UART_Task(void);

應(yīng)用層代碼中實(shí)現(xiàn)回調(diào)函數(shù),并調(diào)用下層函數(shù)。

//?回調(diào)函數(shù):串口數(shù)據(jù)處理
void?OnUartRecvProcess(const?char?*pBuf,?int?length)
{
//?處理串口數(shù)據(jù)
printf("Recv:?%s",?pBuf);
}

int?main()
{
UART_SetRecvCallback(OnUartRecvProcess);

while(1)
{
if?(TimeFlag)
{
UART_Task();
}
}
}

上述示例中通過(guò)函數(shù)指針的方式間接調(diào)用了應(yīng)用層的函數(shù),而且并不違背分層設(shè)計(jì)原則。

如果看代碼不能立即理解的話,可以嘗試通過(guò)下圖理解:

相關(guān)推薦