本文是文章《Tcl/Tk Insight: C/C++ 扩展》的一部分。
#include <tcl.h> #include <stdio.h> int run_tcl(int argc, char *argv[]){ printf("Tcl_FindExecutable ...\n"); Tcl_FindExecutable(argv[0]); // will fatal if no above line. XXX: on windows, used to check stderr channel int ret = TCL_OK; // 创建一个解释器 printf("interp create ...\n"); Tcl_Interp *interp = Tcl_CreateInterp(); if(interp==NULL){ printf("interp create fail\n"); } else { printf("interp create pass\n"); } const char *tcl_library = argv[1]; // where contains the file init.tcl const char *value = Tcl_SetVar(interp, "tcl_library", tcl_library, TCL_GLOBAL_ONLY); printf("tcl_library = %s\n", value); // 执行"init.tcl"进行初始化 if ( Tcl_Init( interp ) != TCL_OK ) { // Error printf("interp init fail\n"); return TCL_ERROR; } else { printf("interp int pass\n"); } if(Tcl_InterpDeleted(interp) != 0){ // 解释器 已经被删除了 printf("interp has been deleted\n"); return TCL_ERROR; } // 执行Tcl命令 const char *script = "set t 3 ; puts $t"; printf("Tcl_Eval = %s\n", script); if(TCL_OK != Tcl_Eval(interp,script )){ printf("Tcl_Eval fail\n"); return TCL_ERROR; } // 执行Tcl文件 printf("Tcl_EvalFile = %s\n", argv[2]); if(TCL_OK != Tcl_EvalFile(interp, argv[2])){ printf("Tcl_EvalFile fail\n"); return TCL_ERROR; } // 删除这个解释器 Tcl_DeleteInterp(interp); return ret; } int main(int argc, char *argv[]){ int ret = run_tcl(argc, argv); printf("exit code = %d\n", ret); return ret; }
其中关键的一步是调用Tcl_Init
以加载文件"init.tcl"。(参见:Tcl 的初始化脚本文件"init.tcl")
一处容易忽略的地方是开头的Tcl_FindExecutable()
, 没有该调用的话,会发生内存访问异常。
/* 执行一段命令, 命令内容保存在 objPtr 中 */ int Tcl_EvalObjEx(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); /************************************************ * 第一次执行时,命令会被编译成字节码 ***********************************************/ /* 执行一个文件, 相对于 source 语句 */ int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName); /* 执行一段命令, 命令内容保存在字符串中 */ int Tcl_Eval(Tcl_Interp *interp, const char *script ); int Tcl_EvalEx(Tcl_Interp *interp, const char *script, int numBytes, int flags); /************************************************ * 直接解析执行,不会编译成字节码 ***********************************************/ /* 执行一条命令 */ int Tcl_EvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj **objv, int flags);
TCL_BASE = /c/some/path/tcl TCL_BASE_WIN = c:/some/path/tcl ttcl: ttcl.c gcc -o $@ -I$(TCL_BASE)/include ttcl.c $(TCL_BASE)/lib/tcl84.lib test: ttcl.exe $(TCL_BASE_WIN)/lib/tcl8.4 test.tcl install: cp $(TCL_BASE)/bin/tcl84.dll .