基於Tiny C compiler的c指令碼混合編程方法

來源:互聯網
上載者:User
 

TCC 簡要介紹:TCC 最有趣的特性是可以用 UNIX 系統上常見的 #!/usr/bin/tcc 的方式來執行 ANSI C 語言寫就的來源程式,省略掉了在命令列上進行編譯和連結的步驟,而可以直接運行 C 語言寫就的來源程式。這樣就能做到像任何一種其它的指令碼語言比如 Perl 或者是 Python 一樣,顯著的加快開發步調。可以像編寫 Shell 指令碼一樣的使用 C 語言,隨便想一想都覺得是一件奇妙的事情。但是 TCC 還有一些其它的特性呢!
  • TCC 的體積非常小,全部原始碼打包壓縮以後不到 200 K 位元組大小,編譯後的 tcc 可執行程式不過 80 K 位元組大小。這意味著我們幾乎可以在任何場合使用 TCC 提供給我們的編寫 C 語言指令碼的能力。這其中當然包括硬碟空間十分緊張的環境,比如嵌入式系統和啟動磁碟片等等。
  • 在給 TCC 的來源程式中可以使用任何在給 GCC 的來源程式中可以使用的動態連結程式庫。TCC 不僅支援標準的 ANSI C 語言,而且也支援 ISO C99 標準和一部分來自於 GCC 的對 C 語言所做的擴充。
  • TCC 直接產生經過部分最佳化的 X86 機器代碼。並不需要產生任何虛擬機器的二進位代碼。據 TCC 作者提供的資料,TCC 的編譯速度比 GNU C 編譯器在不做任何代碼最佳化工作(gcc -O0)的時候都要快。當然啦,要是讓 GCC 做代碼最佳化的話,那麼編譯速度就更加比不上 TCC 嘍。
  • Libtcc庫能夠讓使用者將TCC作為作為動態代碼產生的後端,在libtcc.h中有API的說明,libtcc_test.c是使用libtcc的簡單例子。Libtcc包含了這樣一種思想,使用者可以將程式包含在字串中,然後直接編譯,接下來就可以存取全域符號(函數和變數)。
產生LIBTCC:        由於libtcc是基於linux的,為了能夠產生window下的動態串連庫,我們先要使用mingw/msys編譯,然後用下面的語句產生dll。為了方便msvc使用,還需要再產生lib庫用於連結。整個步驟如下:1) 產生DLLgcc -O2 -shared -Wall -Wl,--export-all-symbols -mpreferred-stack-boundary=2 -march=i386 -falign-functions=0 -fno-strict-aliasing -DTCC_TARGET_PE -DLIBTCC -o libtcc.dll tcc.c2) 產生def pexports libtcc.dll | sed "s/^_//" > libtcc.def 3) 從def產生lib lib /machine:i386 /def:libtcc.def     由於c語言編程需要標頭檔和庫,我們也需要在發布程式的時候帶上include目錄和lib目錄,然後在主程式中指定該路徑。  TCC 和主程式的配合:        在我們的程式中,主要把固定的邏輯放在主程式中,而將變化的東西放在tcc指令碼中。該程式的基本流程如下:       按照使用者的輸入參數開啟截包,按照指定的類型將每一個資料報合適的數組片斷傳給使用者寫的tcc程式,由tcc程式將處理後的資料傳給主函數,由主函數進一步處理,比如寫入檔案中。注意到我們需要處理的可能是rtp包,也可能是沒有rtp頭的包,在輸出的時候,有些碼流也需要加入額外的處理,比如h261和h263需要調用主程式中的函數進行sbit,ebit的拼接;比如h263+的簡單處理,比如h264的流頭的添加,比如音訊直接輸出。所以我們在主程式和tcc程式間不光要傳遞變數,還需要傳遞函數。下面是大概的代碼架構和解釋。 主程式:TCCState *s;建立新的tcc狀態    s = tcc_new();    if (!s) {        fprintf(stderr, "Could not create tcc state/n");        exit(1);    }       添加路徑:       tcc_add_include_path(s,fullinc);       tcc_add_library_path(s,fulllib);        設定輸出方式為記憶體:       tcc_set_output_type(s, TCC_OUTPUT_MEMORY);       編譯一個檔案到tcc中(其實是讀檔案到緩衝區,然後調用了tcc_compile_string)       tcc_compile_file(s,fullpath);       將變數和函數符號加入到tcc環境中去,這樣在tcc中就可以直接使用這些符號       tcc_add_symbol(s, "encodeflag", (unsigned long)&encodeflag);       tcc_add_symbol(s,"f",(unsigned long )&f);       tcc_add_symbol(s,"Enter_H263Decode",(unsigned long)&Enter_H263Decode);       tcc_add_symbol(s,"writeFile",(unsigned long)&writeFile);        做所有的重定位工作,在tcc_get_symbol之前必須調用       tcc_relocate(s);       擷取tcc中的函數和變數符號    tcc_get_symbol(s, &val, "Process");    Process = (pf_Process)val;       tcc_get_symbol(s,&val,"withRtp");       withRtp=(int)(*(int *)val);       tcc_get_symbol(s,&val,"offset");       offset=(int)(*(int *)val);       迴圈處理每一個資料包       while((res = pcap_next_ex( fp, &header, &pkt_data)) >= 0){       。。。調用tcc中的處理函數       Process(&pkt_data[offset],totallen);} 清理tcc環境tcc_delete(s);  TCC 程式#include <stdio.h>#include <stdlib.h> int withRtp=1;int offset=54;unsigned char zero[2]={0,0};unsigned char h264head[4]={0,0,0,1}; extern FILE *f;extern unsigned char encodeflag;extern int writeFile(unsigned char *buf,int len); int Process(unsigned char *pt,int len){       if(encodeflag==0 ||encodeflag==1)       {/*h261或者h263*/              if((pt[0])&0x7==0)              {                     Enter_H263Decode(len,pt,1);              }              else              {                     Enter_H263Decode(len,pt,0);               }                          }       else if(encodeflag==2)       {/*h263+*/        if((pt[0]==0x04) && (pt[1]==0x00))        {                  writeFile(zero,2);                  writeFile(&pt[2],len-2);           }        else if((pt[0]==0x00) && (pt[1]==0x00))        {                  writeFile(&pt[2],len-2);                           }        else        {               printf("not correct 263+ format/n");        }                            }       else if(encodeflag==3)          {/*raw data*/              fwrite(pt,1,len,f);       }       else if(encodeflag==4)       {/*mp3*/              if(pt[0]==0xff && pt[1]==0xfb)              {                     writeFile(&pt[4],len-4);              }              else              {                     printf("not a mp3 header,%02X %02X/n",pt[0],pt[1]);              }                          }       else if(encodeflag==5)       {/*h264*/              writeFile(h264head,4);              writeFile(pt,len);       }       else        {              ;       }            return 0;}  從上面的例子可以看出,使用tcc,可以很容易的處理數組,畢竟,採用其他指令碼語言的話,比如lua,perl等,要想處理數組,要想容易的進行位元運算,還是很麻煩的,而且,c語言畢竟是大多數人熟悉的語言,使用起來很方便。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.