如何在python中實現capl語言裡的回調函數(推薦)
CAPL:回調函數
CAPL是一種程序語言,其中程序塊的執行由事件控制。 這些程序塊被稱為事件程序。在事件程序中定義的程序代碼在事件發生時執行。換句話說,事件程序就是事件函數,當事件函數關聯的事件被觸發時,會自動執行此事件函數函數體。事件函數也稱為回調函數
事件函數的標志就是關鍵字on,比如:
- on key 表示當鍵盤按下小寫字母a時觸發此事件函數執行
- on message 表示當接收到消息時觸發此事件函數執行
- on start 表示當canoe軟件運行時觸發此事件函數執行
- on sysvar 表示系統變量值發生改變時觸發此事件函數執行
還有很多此類函數,你可以通過在capl文件的左側的導航欄裡右擊插入不同類型的事件函數
事件函數的作用是什麼?
就是在程序運行期間,可以隨時監控某種事件的發生,執行對應的操作。比如你想在can總線上監測收到can消息0x11時獲取can消息數據,就可以使用on message 0x11
on message 0x11 { byte msg_bytes[8]; int i; for(i=0;i<8;i++) { msg_bytes[i] = this.byte(i); } }
那為什麼把它稱為回調函數呢?
可能是雖然主程序裡的代碼在從上往下按順序在執行,但是在這期間隻要觸發事件函數的條件發生改變,就會“回頭”執行事件函數。當然,主程序和事件函數是異步執行
這裡有一些註意事項:
Simulation Setup仿真界面插入的Network Node網絡節點,加載的capl腳本是沒有主程序MainTest的
Test Modules和Test Units加載的capl腳本,是不允許使用system類型的事件函數的
Python:回調函數
python執行回調函數,是在調用某個函數時,把回調函數指針當作參數傳入要調用的函數中,在函數內部調用回調函數
def OnEvent_1(): print("callback up") def TriggerFunc(fn): fn() if __name__ == "__main__": TriggerFunc(OnEvent_1)
在執行TriggerFunc()時,通過傳入OnEvent_1()函數指針作為參數,在TriggerFunc()函數體內部調用OnEvent_1()實現回調
所以,OnEvent_1()函數是回調函數,執行TriggerFunc()函數就可以看作觸發回調函數的條件
這裡有兩個註意點:
函數指針是指向函數的指針變量,用函數名表示,不能有括號“()”
調用函數時函數名必須有括號“()”才能調用
capl中的事件函數,有幾個特點:
- 函數體和觸發條件定義明確
- 無限循環監測觸發條件是否觸發
- 和主函數異步執行
所以在python中想實現這些特點,可以這樣:
import time import threading def OnEvent_1(): # 事件函數1 print("OnEvent_1 up") def OnEvent_2(): # 事件函數2 print("OnEvent_2 up") class RegistEvents(): # 全局變量,存入事件函數指針和對應的觸發條件 registEvents = {} # 存入key:value,key是事件函數指針,value是觸發此事件函數的條件 def TriggerFunc(): # 異步函數,用來監測觸發條件是否觸發,如果觸發就執行對應的函數 currentRegistEvents = {} # 當前的事件和對應條件存入這裡 for event in RegistEvents.registEvents.keys(): currentRegistEvents[event] = RegistEvents.registEvents[event] while True: time.sleep(0.01) for event in RegistEvents.registEvents.keys(): if currentRegistEvents[event] != RegistEvents.registEvents[event]: event() currentRegistEvents[event] = RegistEvents.registEvents[event] if __name__ == "__main__": RegistEvents.registEvents[OnEvent_1] = 0 # 對事件函數OnEvent_1和它的條件進行委托 RegistEvents.registEvents[OnEvent_2] = 0 # 對事件函數OnEvent_2和它的條件進行委托 t = threading.Thread(target = TriggerFunc) # 對監測觸發條件的函數創建線程,異步執行 t.start() time.sleep(1) RegistEvents.registEvents[OnEvent_1] = 1 # 觸發條件本來是0,現在設置為1 RegistEvents.registEvents[OnEvent_2] = 1 time.sleep(1) RegistEvents.registEvents[OnEvent_1] = 2 # 觸發條件本來是1,現在設置為2 RegistEvents.registEvents[OnEvent_2] = 2
由於python中並沒有像capl中那樣對不同類型觸發的事件函數進行定義(on key/on message等),所以這裡我們可以借鑒c sharp語言中的委托,定義委托,然後註冊事件,最後執行
這裡用一個字典來註冊(存入)事件和對應的觸發條件,key是事件函數指針,value是觸發條件(其實是事件函數指針關聯的一個值)
為什麼不是key是觸發條件,value是函數指針呢?
因為事件函數的觸發條件需要改變,而字典中的key寫入後是無法改變的,但是value是可以改變的,所以value作為觸發條件會更好
到此這篇關於如何在python中實現capl語言裡的回調函數的文章就介紹到這瞭,更多相關python回調函數內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- python threading模塊的使用指南
- 分析Python感知線程狀態的解決方案之Event與信號量
- Python解析器Cpython的GIL解釋器鎖工作機制
- 如何讓python程序正確高效地並發
- Python多線程以及多線程中join()的使用方法示例