本文是文章《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 .