TCL和C的混合編程

來源:互聯網
上載者:User

標籤:style   http   使用   檔案   io   for   cti   代碼   

Tcl作為一種指令碼語言具有非常高的效率,因此在實際的設計中我們可以採用TCl來完成一些對效能要求不是很高但是用C卻需要很長開發週期的任務,而只把執行時間有很高的要求的部分採用C語言設計

1 在C中引用TCL時要包含標頭檔<tcl.h>編寫,c中的所有tcl命令均通過TCL解譯器Tcl_Interp完成。他是一個C結構體

主要的函數有

Tcl_Interp * Tcl_CreateInterp();//產生tcl解譯器
Tcl_DeleteInterp(Tcl_Interp *interp); //刪除tcl解譯器
Tcl_InterpDeleted(Tcl_Interp *interp); //檢測解譯器是否已經被刪除,未被刪除則返回非零值
Tcl_Interp *Tcl_CreateSlave(Tcl_Interp *Interp,CONST char slavename, int issafe ); //建立從解譯器,issafe決定是否建立安全的解譯器
int Tcl_IsSafe(Tcl_Interp *interp);//檢測是否為安全的解譯器,安全返回1, 不安全返回0
int Tcl_MakeSafe(Tcl_Interp *interp); //產生安全的解譯器
Tcl_Interp *Tcl_GetSlave(Tcl_Interp *Interp, const char *slavename);//返回從解譯器
Tcl_Interp *Tcl_GetMaster(Tcl_Interp *Interp);//擷取從解譯器的主解譯器
Tcl_Interp *Tcl_GetInterpPath(Tcl_Interp *askinterp, Tcl_interp *slaveInterp);//成功返回TCL_OK,否則返回TCL_ERROR,askinterp會被設為askinterp和slaveInterp之間的路徑。
一.tcl中調用c/c++  主要是利用c/c++處理複雜邏輯的能力,對於tcl來說,實際上就是一個擴充,因為你可以通過Tcl_CreateCommand函數,建立出一個新的tcl命令。  具體操作方法需要分情況: 1.如果當前tcl版本支援load命令文法:load libpackage.so意義:在tcl中,當一個動態庫libpackage.so被裝載時,tcl會調用其中名為package_Init的函數,記住,名字一定不能錯,包括大小寫。這樣,你就獲得了一個入口,可以進入c/c++啦,你可以幹任何事,當然,最重要的還是Tcl_CreateCommand了。 函數原型:Tcl_Command Tcl_CreateCommand(interp, cmdName, proc, clientData, deleteProc)意義:建立一個新的tcl命令cmdName,對應的操作函數指標為proc。 這裡以一個階乘演算法為例:目的是提供一個名為myfract的tcl命令,只接收一個參數,例如:myfract 10表示計算10的階乘。 【fract.c】:#include "tcl.h"int Tcl_myfract(ClientData notUsed, Tcl_Interp *interp, int argc, char **argv){  int i, j;  double res=1.0;  char re[30];  if (argc > 2)  {    Tcl_SetResult(interp, "wrong args: should be myfract", TCL_VOLATILE);    return TCL_ERROR;  }  if (Tcl_GetInt(interp, argv[1], &i) != TCL_OK)  {    return TCL_ERROR;  }  for (j=1;j<=i;j++)    res *= j;  sprintf(re,"%le",res);  Tcl_SetResult(interp, re, TCL_VOLATILE);  return TCL_OK;}int Fract_Init(Tcl_Interp *Interp) {  Tcl_CreateCommand (Interp, "myfract", (Tcl_CmdProc *)Tcl_myfract, (ClientData)0, 0);  return TCL_OK;} 【Makefile】:t = libfract.soall: $tclean:  rm -f $t corelibfract.so: fract.c  gcc -I. -shared -o [email protected] fract.c 【test.tcl】: #!/usr/bin/tclshload ./libfract.soset tcl_flag  [catch {myfract 2} return_str]if {$tcl_flag != 0} {  puts "OK:$return_str"} else {  puts "Error:$return_str"} 運行:linux:~/test/tcl # ./test.tcl2.000000e+00 【小結】:這裡有兩點需要注意,第一,Fract_Init是由TCL到c/c++的入口,而Tcl_CreateCommand則是由c/c++到TCL的入口;第二,編譯動態庫時不必連結tcl的開發庫,因為這裡僅僅需要引用。     還有swig可以使用 【fract.i】:%module fractextern double myfract(int);swig的文法這裡就不詳述了,具體可參見www.swig.org。第一行表示模組名稱叫做fract,對應前面的c/c++代碼,就是說要建立的動態庫叫做libfract.so;第二行表示將要匯出的函數,這個函數是需要你自己定義的。 【fract.c】:double myfract(int n){  double res=1.0;  int j;  for (j=1;j<=n;j++)  {    res *= j;  }  return(res);} 【Makefile】:t = fract_wrap.c libfract.soall: $tclean:  rm -f $t core *.doc *.ofract_wrap.c: fract.i  swig -tcl fract.ilibfract.so:fract_wrap.c  gcc -c fract.c fract_wrap.c 運行:linux:~/test/tcl/swig # ./test.tcl2.0 2.如果當前tcl版本不支援load命令  我不知道哪個版本會這麼原始,但即便如此,仍然有解決方案,那就是把擴充模組靜態連結到執行檔案中去,具體操作如下:【main.c】:#include <tcl.h>#include <stdio.h>int Tcl_AppInit(Tcl_Interp *interp);int main(int argc, char *argv[]) {  Tcl_Main(argc, argv, Tcl_AppInit);}int Tcl_AppInit(Tcl_Interp *interp) {  /* Initialize Tcl */  if (Tcl_Init(interp) == TCL_ERROR) {    return TCL_ERROR;  }  /* Initialize our extension */  if (Fract_Init(interp) == TCL_ERROR) {    return TCL_ERROR;  }  return TCL_OK;} 【Makefile】:t = mainTCL_LIBS = -L/usr/lib -ltcl8.4all: $tclean:  rm -f $t coremain:main.c fract.c  gcc -I. ${TCL_LIBS} -o [email protected] main.c fract.c 運行:linux:~/test/tcl # ./main% myfract 84.032000e+04% exitlinux:~/test/tcl # ldd main        linux-gate.so.1 =>  (0xffffe000)        libtcl8.4.so => /usr/lib/libtcl8.4.so (0x40030000)        libc.so.6 => /lib/tls/libc.so.6 (0x400d8000)        libdl.so.2 => /lib/libdl.so.2 (0x401f1000)        libm.so.6 => /lib/tls/libm.so.6 (0x401f5000)        /lib/ld-linux.so.2 (0x40000000)       我們發現,代碼中重寫了Tcl_AppInit函數,在tcl手冊中該函數被形容為一個``hook‘‘ procedure,很奇妙的東西。因為最後會建立一個類似tclsh的執行檔案,所以,tcl開發庫必須連結上。 二.c/c++中調用tcl  之所以會有這樣的做法,主要是想利用tcl的客戶化能力。  例如把流程寫在tcl指令碼中,c/c++代碼中僅僅執行Tcl_EvalFile就可以了,對於不同的服務,我們可以藉助某種手段,綁定一個流程指令碼,這樣,當增加新的服務時或者服務流程需要變更時,不必修改源碼,只要增加或修改設定檔/指令檔即可,這也就實現了我們所說的客戶化。  我們只討論幾個常用的函數:Tcl_CreateInterp    - 建立一個tcl解譯器Tcl_Eval            - 執行一個tcl命令Tcl_VarEval         - 類似Tcl_Eval,只不過這個命令是被參數串起來的Tcl_EvalFile        - 執行一個tcl指令碼Tcl_SetVar          - 設定tcl變數Tcl_GetVar          - 擷取tcl變數的值 下面是一個用法測試:【test.c】:#include <tcl.h>#include <string.h>#include <stdlib.h>#include <assert.h>int main(){  Tcl_Interp* interp;  char    *p;  int tclres;  //create interpreter  interp = Tcl_CreateInterp();  /*   * Test Tcl_SetVar   */  char *varname = "SERVICE_NAME";  char *varval = "MyServer";  p = (char *)Tcl_SetVar(interp, varname, varval, TCL_GLOBAL_ONLY);  assert ( p!=NULL && !strncmp(p, "MyServer", 8) );  /*   * Test Tcl_GetVar   */  p = (char *)Tcl_GetVar(interp, "SERVICE_NAME", TCL_GLOBAL_ONLY);  assert ( p!=NULL && !strncmp(p, "MyServer", 8) );  /*   * Test Tcl_Eval   */  tclres = Tcl_eval_r(interp, "set CFG_val world");  assert ( tclres == TCL_OK) ;  p = (char *)Tcl_GetVar(interp, "CFG_val", TCL_GLOBAL_ONLY);  assert ( p!=NULL && !strncmp(p, "world", 5) );  /*   * Test Tcl_VarEval   */  char *home = "./";  tclres = Tcl_Vareval_r(interp, "source ", home, "test.cfg", NULL) ;  assert ( tclres == TCL_OK) ;  p = (char *)Tcl_GetVar(interp, "CFG_val", TCL_GLOBAL_ONLY);  assert ( p!=NULL && !strncmp(p, "hello", 5) );  /*   * Test Tcl_EvalFile   */  char *path = "./test.cfg";  tclres = Tcl_EvalFile(interp, path);  assert ( tclres == TCL_OK) ;  p = (char *)Tcl_GetVar(interp, "CFG_val", TCL_GLOBAL_ONLY);  assert ( p!=NULL && !strncmp(p, "hello", 5) );  //END  printf("OK/n");  } 【Makefile】:t = testTCL_LIBS = -L/usr/lib -ltcl8.4all: $tclean:  rm -f $t coretest: test.c  gcc -I. ${TCL_LIBS} -o [email protected] test.clinux:~/test/tcl/test # ./testOK 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.