libmodbus
Copyright 2021, 月下麒麟
有關結構在第一篇就有提及相關實作,
此篇會著重的技巧function pointer與callback function及自我理解
在理解source過程中,發現多處出現modbus_t的使用
經trace之後,發現它是某個名為 _modbut_t struct所定義而成
沿著這個思路去理解function pointer與callback function
callback function-
*
A callback function is a function that is passed to another function as an argument.
*
Two types of callback functions:
-->
Synchronous: executed immediately.
-->
Asynchronous: executed later.
*
Commonly used in event-driven systems.
*
In C, implement using function pointers.
Reference:Callback Functions | C Programming
讓我們就先來之前看原始碼
Reference:libmodbus/src/modbus-private.h
Reference: libmodbus/src/modbus-rtu.c
看完上面的code,想必會覺得這兩段長得很像
Reference:libmodbus/src/modbus-rtu.c
延伸:其中(*receive)的實作範例
於typedef struct…的地方先定義出了 _modbus_backend結構的細節,
與該結構變數modbus_backend_t
並在modbus_rtu.c裡,
使用結構變數(modbus_backen_t)作為 _modbus_rtu_backend的型態,
進行初始值的賦予,只是初值內容是macro與匿名函式
小結:
modbus_backend_t作為prototype,
提供結構成員操作時可依據宣告的初值去實作細節。
Reference:Pointers as Structure Member in C
可以觀察到利用結構成員與function pointer皆可取得宣告初值的內容
Reference:Youtube: Callback Functions | C Programming
發現到callback function就是利用函式做為指標
typedef float (*op_t)(int);
可理解op_t為指向函式的函式指標且帶有一個整數引數值,並回傳值為浮點數格式
該實作是利用cplusplus: qsort 函式本身就使用到callback function,
從其引數(argument)可發現到int (*compar) (const void* p1, const void* p2);
利用qsort這個prototype然後依序對arr的元素位址取值比較大小,再將其重新排列。
當有需要排列的list,將其丟入(呼叫)qsort函式,
當qsort排列完後,會再將結果吐出來(回傳),
並再回到主程式接續執行,
這一動作可理解為callback function。
(另外,該qsort也有應用到function pointer概念)
上面可觀察到,
s1或t1就是求得 (array size * type size),改變型別會有不同結果
s2或t2就是求得陣列大小,
sizeof(arr)/sizeof(arr[0]),等價於
sizeof(arr)/sizeof(int)
但是前者的寫法比較好,若改變陣列元素型別,後續程式無須再做變更。
Reference:Function Pointers and Callbacks in C
這篇的範例,滿清楚的,但我稍微修改,將它合併在一個main.c裡
可參考這段程式,更能體會callback function的意義。
呼叫函式與取得位址
結論:
callback的精神在於第一次遇到它時,只去取得它的位址
(注意函式後面沒括號)
所以將其位址保留在變數ptr_my_callback
接著,等到你想去執行它時,再將其位址丟到負責呼叫別人做事的函式裏頭
它就會真正去做事了
日常比喻的話,你在掃地掃到一半(主程式),
外面下雨(事件發生),
你家人就呼叫你去收衣服(系統要主程式緊急的先執行),
收完衣服,你回來繼續完成你的打掃(回到主程式)。
最後,引述一段參考文章的話:
Just remember, callback is nothing but passing the function pointer to the code from where you want your handler/callback function to be invoked.
(真好,今天又進步一點點了,
另外,感謝師仔的耐心提點與詳細解釋,才有這篇文章的產出,
內容細節編排上,還是相當凌亂,還有很多進步的空間,
希望能幫助路過於此,正在學習的你)