當前位置:首頁 > 公眾號精選 > 嵌入式微處理器
[導讀]▍很懶很操心 有一次,我在項目開發(fā)中想監(jiān)控某段空間數(shù)據的大小,即這段空間在MCU中非常有限,希望每個版本在集成軟件的時候都想獲取其使用了多少空間,防止某些愣頭青不珍惜內存,亂塞東西。而這段空間,我定義了一個神一樣的結構體映射到這個空間,即其他開


很懶很操

有一次,我在項目開發(fā)中想監(jiān)控某段空間數(shù)據的大小,即這段空間在MCU中非常有限,希望每個版本在集成軟件的時候都想獲取其使用了多少空間,防止某些愣頭青不珍惜內存,亂塞東西。而這段空間,我定義了一個神一樣的結構體映射到這個空間,即其他開發(fā)人員只要在結構體增加元素即可(我使用洪荒之力將宏定義發(fā)揮到淋漓盡致才做到的,至于怎么實現(xiàn)的細節(jié)就不在這個文章討論了,后續(xù)再寫篇文章裝裝X)。

計算這個結構體空間,要求:

  1. 在軟件集成階段就獲得這個結構體大小,而不是MCU運行的時候;(自動執(zhí)行)

  2. 計算這個結構體大小,不要增加刪除原程序代碼;(悄無聲息)

  3. 方便集成工程師使用,不增加使用難度;(簡單易用)

  4. 不因為人操作的原因,而導致計算結果不準確,即自動化執(zhí)行輸出結果。(無人為干擾)

總之,做這件事的目的是:每次集成的時候自動輸出結果(很懶),也不行交給其他小伙伴去手工計算,或者更改原來的結構代碼去計算這個空間,怕其亂來搞壞了原來的代碼(很操心)。

再總之:能讓電腦干的活,干嘛要讓人去干!

于是,我就突發(fā)奇想,寫個腳本唄。

那么啥子腳本可以計算C語言的結構體大???

身為優(yōu)秀的嵌入式”工程師,對這種將C語言“嵌入”到腳本中的事情肯定是要研究一番的。

Note:為了方便描述,我將具體項目細節(jié)和裝X的過程隱去,并將這個神一樣的結構體簡化為:

 typedef struct
 {
     unsigned char item_a[2];
     unsigned char item_b[3];
     unsigned char item_c[5];
     unsigned char item_d[8];
     unsigned char item_e[33];
     unsigned char item_fxxk[1];
     unsigned char item_fxxxk[2];
     unsigned char item_fxxk_any[55];
     // add items here...
 }typeStructData;

將C/C++代碼嵌入Python

人生苦短,我用Python

溫馨提示,使用以下方法,請?zhí)崆鞍惭b:

  1. Python
  2. GCC(例如Windows上的MinGW)
  3. 用pip安裝pyembedc(pip install pyembedc

注意:Python的版本位數(shù)要跟GCC的對應,例如都選32位的。

方法1:Python調用exe方式

步驟:

  1. 在一個臨時C文件里,編寫臨時main函數(shù);

  2. 用GCC構建編譯,生成exe;

  3. 通過腳本(此處選擇Python)調用運行輸出結果;

  4. 刪除臨時C文件和exe文件。

接上代碼看看

 // struct.h
 
 typedef struct
 {
     unsigned char item_a[2];
     unsigned char item_b[3];
     unsigned char item_c[5];
     unsigned char item_d[8];
     unsigned char item_e[33];
     unsigned char item_fxxk[1];
     unsigned char item_fxxxk[2];
     unsigned char item_fxxk_any[55];
 }typeStructData;
 import os
 
 c_main = r'''
 #include <stdio.h>
 #include "struct.h"
 int main(void)
 {
    printf("size: %d\n", sizeof(typeStructData));
    return 0;
 }
 '''
 def cal_struct_size():
     f_c_main = 'xxxxsizeofstructxxxx.c'
     f_run = 'xxxxsizeofstructxxxx.exe'
     with open(f_c_main, 'w') as f: f.write(c_main)
     gcc_compile = "gcc %s -o %s"%(f_c_main, f_run)
 
     os.system(gcc_compile)
     os.system(f_run)
     if os.path.exists(f_c_main): os.remove(f_c_main)
     if os.path.exists(f_run): os.remove(f_run)
 
 if __name__ == "__main__":
     cal_struct_size()

方法2:Python調用lib方式

總覺得用Python調用exe的方式有點low,再進一步,那就調用lib吧,例如調用.so內的函數(shù)或者變量。

步驟跟方法1類似:

  1. 在一個臨時C文件里,編寫臨時main函數(shù);

  2. 用GCC構建編譯,生成lib(.so);

  3. 通過Python調用運行輸出結果;

  4. 刪除臨時C文件。

Python調用lib庫有個好處,可以調用其里面的具體函數(shù)等。

 // struct.c
 
 #include <stdio.h>
 
 typedef struct
 {
     unsigned char item_a[2];
     unsigned char item_b[3];
     unsigned char item_c[5];
     unsigned char item_d[8];
     unsigned char item_e[33];
     unsigned char item_fxxk[1];
     unsigned char item_fxxxk[2];
     unsigned char item_fxxk_any[55];
 }typeStructData;
 
 int get_struct_size(void)
 {
     return sizeof(typeStructData);
 }
 import ctypes
 import os
 
 os.system('gcc -shared -Wl,-soname,struct -o struct.so -fPIC struct.c')
 
 struct_size = ctypes.cdll.LoadLibrary('./struct.so')
 
 def cal_struct_size():
     s = struct_size.get_struct_size()
 
     print("size: %d"%s)
 
 if __name__ == "__main__":
     cal_struct_size()
     # if os.path.exists('struct.so'): os.remove('struct.so')

貌似有個小問題,如果想在腳本里面刪除這個.so文件,會出現(xiàn)問題,因為沒有辦法unload這個.so。另外,關于這個話題,請參考:https://stackoverflow.com/questions/359498/how-can-i-unload-a-dll-using-ctypes-in-python

方法3:Python調用C源碼方式

調用exe和調用lib,都覺得很low,怎么辦,能不能直接插入C源碼呢?

那就用pyembedc吧,Python可以訪問C的變量,C也可以訪問Python的變量,是不是炫酷吊炸天。

例1,訪問C內部變量

 # callstruct_inline1.py
 
 from pyembedc import C
 
 struct_str = r'''
    typedef struct
    {
        unsigned char item_a[2];
        unsigned char item_b[3];
        unsigned char item_c[5];
        unsigned char item_d[8];
        unsigned char item_e[33];
        unsigned char item_fxxk[1];
        unsigned char item_fxxxk[2];
        unsigned char item_fxxk_any[55];
    }typeStructData;
    struct_size = sizeof(typeStructData);
 
 '''
 struct_size = 0
 struct_f = C(struct_str)
 print('size: %d\n'%struct_size)

例2,訪問C內部函數(shù)

 # callstruct_inline2.py
 
 from pyembedc import embed_c
 
 struct_str2 = r'''
    typedef struct
    {
        unsigned char item_a[2];
        unsigned char item_b[3];
        unsigned char item_c[5];
        unsigned char item_d[8];
        unsigned char item_e[33];
        unsigned char item_fxxk[1];
        unsigned char item_fxxxk[2];
        unsigned char item_fxxk_any[55];
    }typeStructData;
     
    int get_struct_size(void)
    {
        return sizeof(typeStructData);
    }
 '''
 struct_c = embed_c(struct_str2)
 print('size: %d\n'%struct_c.get_struct_size())

實際上,以上的操作,也是這個庫偷偷地調用了GCC來編譯C代碼的(只是不是顯式讓你看到而已),你不安裝對應版本的GCC也是做不到的。

順便說是,這個pyembedc有幾個方式:

Functionspyembedc.C(string) -> intpyembedc.inline_c(string) -> intpyembedc.inline_c_precompile(string) -> int

These functions will compile string containing the C/C++ code or directives (see below) and then link dynamically and run the code.

string is C/C++ code that can be used within a function. It can contain any valid C/C++ expression that your compiler will support.

The C function will automatically provide references to all local Python variables for use in your code to read or write as if they were basic types or arrays.

The inline_c and inline_c_precompile fucntion will not provide references to local Python variables and thus is faster and consumes less memory.

pyembedc.embed_c(string) -> cdllpyembedc.embed_c_precompile(string) -> cdll

These functions are used to compile code but not execute immediately. They return a CDLL object (see the CDLL python module) that can be executed later.

更多內容,請見:https://github.com/ftrias/pyembedc


將C/C++代碼嵌入Ruby

生活詩意,我用Ruby

能把C代碼塞進Python,當然也能塞進Ruby。對于在Ruby上插入C源碼,給大家安利一個庫RubyInline。

Inline允許您在Ruby代碼中編寫外部代碼。它會自動確定相關代碼是否已更改,并僅在必要時進行構建。然后將擴展自動加載到定義擴展的類/模塊中。您甚至可以編寫額外的構建器,使您可以用任何語言編寫Inline代碼。使用Inline :: C作為Module,并在Module#inline中查找所需的API。

RubyInline還有以下Features:

  • 快速,輕松地內嵌在ruby腳本中的C或C ++代碼。

  • 可擴展以與其他語言一起使用。

  • 紅寶石和C基本類型之間的自動轉換* char,unsigned,unsigned int,char *,int,long,unsigned long

  • inline_c_raw用于自動轉換不充分時。

  • 僅當內聯(lián)代碼已更改時才重新編譯。

  • 假裝是安全的。

  • 僅需要標準的ruby庫,無需下載其他內容。

 require "inline"
 class MyTest
     inline do |builder|
         builder.c "
            long factorial(int max) {
                int i=max, result=1;
                while (i >= 2) { result *= i--; }
                return result;
            }"
         end
 end
 t = MyTest.new()
 factorial_5 = t.factorial(5)
 require 'inline'
 class MyTest
     inline(:C) do |builder|
         builder.include '<iostream>'
         builder.add_compile_flags '-x c++', '-lstdc++'
         builder.c '
            void hello(int i) {
                while (i-- > 0) {
                    std::cout << "hello" << std::endl;
                }
            }'
     end
 end
 t = MyTest.new()
 t.hello(3)
 

是不是很好玩,是不是很想試試?但是我告訴你,我在Windows上沒搞成功,但在Linux上搞起來了。應了網上某句話:想學Ruby,就用Linux吧,別在Windows上瞎折騰。話說回來,這個嵌入式C源碼的用法,個人感覺Ruby的比Python的簡潔直觀。該用哪種方法,看實際需要吧。更多內容,詳見:https://github.com/seattlerb/rubyinline


總結

想將C/C++塞進腳本,需要借助GCC,它才是讓你裝逼讓你飛的前提條件。


本文授權轉載自公眾號“嵌入式軟件實戰(zhàn)派”,作者實戰(zhàn)派師姐


-END-




推薦閱讀



【01】嵌入式系統(tǒng)中常用的IIC與SPI,這兩種通訊方式該怎么選?
【02】嵌入式必看:Linux內存管理那些事兒
【03】嵌入式項目是如何評估系統(tǒng)所需的RAM和ROM用量的?
【04】嵌入式和單片機不一樣?那它們的區(qū)別在哪?
【05】嵌入式開發(fā)碰到無法解決的問題?編程的凹凸性有妙用?。ǜ?a href="/tags/C代碼" target="_blank">C代碼


免責聲明:整理文章為傳播相關技術,版權歸原作者所有,如有侵權,請聯(lián)系刪除

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關注更多精彩內容

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉