相關:
1 引言
本文是 pymavlink 源碼剖析 文章的第二篇。上一篇 pymavlink 源碼剖析(一)之XML文件的數據解析 主要是分析 pymavlink
對 MAVLINK XML 格式的定義文件是如何解析的,這一篇則分析 pymavlink
是如何在解析獲得的結果的基礎上生成目標代碼的。本篇主要關注於 C
的目標代碼生成的實現。
如果對 MAVLink 協議還不太熟悉請參考文章目錄下方 “相關” 裏面給出的鏈接。
2 C 代碼生成
pymavlink
生成 C 的原理是模板填充 — 給出代碼模板然後把從 XML
中解析處的相關參數填充到其中。對應於C 代碼生成的函數主要在 mavgen_c.py
這個文件裏面。 在 mavgen_c.py
文件中定義瞭如下五個函數:
generate
: 代碼生成入口函數generate_main_h
: 生成主頭文件,所謂主頭文件即以XML
文件名的去掉後綴來命名的文件;generate_mavlink_h
: 生成mavlink.h
文件;generate_message_h
: 生成各個message 的頭文件;generate_one
: 由generate
調用,分別對每一個XML
生成頭文件;generate_version_h
: 生成version.h
文件,其中包括了 MAVLink 的版本號,代碼生成時間等;generate_testsuite_h
生成testsuite.h
文件,testsuite.h
爲測試生成的頭文件的代碼。
這裏首先從generate
函數看起
703 def generate(basename, xml_list):
704 '''generate complete MAVLink C implemenation'''
705
706 for idx in range(len(xml_list)):
707 xml = xml_list[idx]
708 xml.xml_idx = idx
709 generate_one(basename, xml)
710 copy_fixed_headers(basename, xml_list[0])
從這段代碼可以看出其只是對傳入進來的 xml_list
列表調用 generate_one
進行解析,然後調用了 copy_fixed_headers
函數進行收尾。 對於generate_one
函數相對略複雜單獨放在 第3節 說明,這裏先分析copy_fixed_headers
函數。
519 def copy_fixed_headers(directory, xml):
520 '''copy the fixed protocol headers to the target directory'''
521 import shutil, filecmp
522 hlist = {
523 "0.9": [ 'protocol.h', 'mavlink_helpers.h', 'mavlink_types.h', 'checksum.h' ],
524 "1.0": [ 'protocol.h', 'mavlink_helpers.h', 'mavlink_types.h', 'checksum.h', 'mavlink_conversions.h' ],
525 "2.0": [ 'protocol.h', 'mavlink_helpers.h', 'mavlink_types.h', 'checksum.h', 'mavlink_conversions.h',
526 'mavlink_get_info.h', 'mavlink_sha256.h' ]
527 }
528 basepath = os.path.dirname(os.path.realpath(__file__))
529 srcpath = os.path.join(basepath, 'C/include_v%s' % xml.wire_protocol_version)
530 print("Copying fixed headers for protocol %s to %s" % (xml.wire_protocol_version, directory))
531 for h in hlist[xml.wire_protocol_version]:
532 src = os.path.realpath(os.path.join(srcpath, h))
533 dest = os.path.realpath(os.path.join(directory, h))
534 if src == dest or (os.path.exists(dest) and filecmp.cmp(src, dest)):
535 continue
536 shutil.copy(src, dest)
可以看出,copy_fixed_headers
函數的主要功能就是依據當前的 MAVLink 版本把一些相對不要模板生成的頭文件挨個複製到輸出文件夾下。