小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Tiny C Compiler 嵌入式使用幫助

 quasiceo 2014-01-15

Tiny C Compiler 嵌入式使用幫助

Lua這種東西大家肯定不陌生了,要說這類的嵌入式腳本語言對寫程序來說,確實(shí)會(huì)方便不少.但是lua有幾個(gè)缺點(diǎn)不得不提.

1.lua的語法很怪異,這對于習(xí)慣了腳本開發(fā)的人員也許沒什么,但是對于一個(gè)ASM和C++的程序員無疑的很痛苦的.

2.lua的執(zhí)行速度很慢,極端的情況下,可能達(dá)到同類二進(jìn)制執(zhí)行速度的及百分之一.基本上不能用來代替主程序做大計(jì)算量的工作.

我之前也是用lua,痛苦不言而喻,后來在有花的提醒下,發(fā)現(xiàn)了這么一個(gè)代替lua的好東西--Tiny C Compiler.

TCC的優(yōu)點(diǎn):

1.她是一個(gè)完全符合ISOC99的規(guī)范的C語言編譯器.用在嵌入式腳本上,對于C程序員,基本沒有障礙.

2.她是直接編譯化的嵌入式腳本,只要事先編譯了腳本,執(zhí)行的時(shí)候?qū)τ谛视绊懳⒑跗湮?

3.由于她是個(gè)編譯器,所以所有的windows函數(shù),C運(yùn)行庫函數(shù),甚至你可以找到的任何DLL,LIB都可以被她用來作為擴(kuò)充函數(shù).

有這么多有點(diǎn)當(dāng)然是好的,但是很不幸,這東西的資料實(shí)在少的可憐,那干巴巴的一點(diǎn)點(diǎn)文檔是專門說編譯器的,對于嵌入式上的文檔幾乎找不到(google搜索tcc_set_lib_path這類函數(shù)名,結(jié)果居然是0,可見其保密性做的多好.-_-).唯一的途徑就是閱讀源代碼摸索出其用途.

好在關(guān)于怎么將tcc用在嵌入式上的方法,還是很簡單的,不花多少時(shí)間,就能搞定,為了更多的人不再重復(fù)的勞動(dòng),我寫了這么一篇文章.我用的是0.9.25版本,以下默認(rèn)為這個(gè)版本.

//////////////////////////////////////////////////////////////////////////////////////////////////

首先,tcc是可以直接混在工程中編譯的.參考源代碼中的那份"libtcc_test.c"文件,這里說一下編譯方法:

1.include了TCC源碼目錄下的libtcc.h文件.

2.在工程中添加config.h頭文件,內(nèi)容如下:

#define TCC_VERSION "0.9.25"
#define TCC_TARGET_PE 1
#define CONFIG_TCCDIR "."
#define CONFIG_SYSROOT ""

3.調(diào)用tcc_set_lib_path函數(shù)設(shè)置tcc目錄(這點(diǎn)下面代碼中有詳細(xì)說明).

4.tcc_delete(s);必須在func之后調(diào)用.(這點(diǎn)下面代碼中有詳細(xì)說明)

注意:如果你的Tcc腳本中,使用了運(yùn)行庫.記得把工程設(shè)置為ASCII,可能因?yàn)門CC不支持unicode,如果你的工程是Unicode,在Tcc獲取運(yùn)行庫函數(shù)指針的時(shí)候,將獲取不到.(或許還有其他辦法,我沒再琢磨了)

//////////////////////////////////////////////////////////////////////////////////////////////////

然后.其實(shí)大多數(shù)人用的是下面這些:

直接參與編譯的方法很別扭,或者你的工程是Unicode的,那可以采用獨(dú)立編譯成Dll(關(guān)于獨(dú)立編譯的方法和上面直接參與工程編譯的差不多,就不累述了,我已經(jīng)獨(dú)立編譯出了一個(gè)包提供給大家),然后動(dòng)態(tài)鏈接的方式使用Tcc,方法如下:

1.下載我提供的Tcc系統(tǒng)包(在我的網(wǎng)絡(luò)硬盤,blog首頁有)--libtcc.rar

2.將代碼解壓縮到指定的目錄(下面例子中比如說是"Z:\\tcc"目錄).

3.將包中的.libtcc_zv.dll,拷貝到你的程序當(dāng)前目錄(或者系統(tǒng)目錄)

4.編譯如下代碼(wind32-console工程).

#include <stdio.h>

//這是tcc的連接目錄
#include "Z:\\tcc\\tcc\\tcc.h"
#pragma comment(lib, "Z:\\tcc\\tcc\\Libtcc.lib")

//這是打算加入到TCC中的代碼
int add(int a, int b)
{
return a + b;
}

//這是TCC腳本(姑且算作腳本吧.lua看習(xí)慣了.)
char my_program[] =
"int fib(int n)\n"
"{\n"
"    if (n <= 2)\n"
"        return 1;\n"
"    else\n"
"        return fib(n-1) + fib(n-2);\n"
"}\n"
"\n"
"int foo(int n)\n"
"{\n"
"    printf(\"Hello World!\\n\");\n"
"    printf(\"fib(%d) = %d\\n\", n, fib(n));\n"
"    printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n"
"    return 0;\n"
"}\n";

int main(int argc, char *argv[])
{
//申請一個(gè)TCC對象
TCCState *s = tcc_new();

//加入Tcc連接目錄
//注意,這里雖然有l(wèi)ib字樣,但不是lib目錄,這個(gè)目錄下應(yīng)該包含lib目錄和include目錄
//tcc會(huì)自動(dòng)的在這個(gè)目錄下加上/lib和/include,以備使用
//這個(gè)目錄用\\或者用/都可以,TCC源碼中用的是/
tcc_set_lib_path(s, "Z:\\tcc");

//設(shè)置輸出模式為內(nèi)存
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);

//編譯代碼(也就是編譯腳本成可執(zhí)行文件)
if (tcc_compile_string(s, my_program) == -1)
{
   printf("compile error\n");
   return 1;
}

//將exe中的add函數(shù)的符號(hào)加入到編譯后的腳本中
tcc_add_symbol(s, "add", add);

//重定位代碼中的符號(hào),并輸出到用戶指定內(nèi)存中
int size = tcc_relocate(s, NULL);
if (size == -1) return 1;
void *mem = malloc(size);
tcc_relocate(s, mem);

//獲取tcc腳本中的一個(gè)函數(shù)符號(hào)
void (*func)(int);
func = (void(*)(int))tcc_get_symbol(s, "foo");
if (!func) return 1;

//執(zhí)行該函數(shù)
func(32);

//注意,原tcc例子中,這個(gè)delete是放在func之上的
//貌似我讀源碼的時(shí)候,如果這個(gè)在func調(diào)用之前調(diào)用,那么可能會(huì)釋放一些dll/
//比如msvcrt.dll,這樣,tcc腳本中的一些printf這類CRT函數(shù)就將會(huì)被連接到一個(gè)無效地址
//引發(fā)異常.所以這個(gè)delete只好放在func之后調(diào)用了.
tcc_delete(s);

//釋放重定位之后存放的內(nèi)存.
free(mem);

return 0;
}

***

VC6編譯的時(shí)候,TCC的頭文件中出現(xiàn)long long定義錯(cuò)誤,改為__int64即可.2003之后版本的VC沒有這個(gè)問題.

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多