Tcl 是个很老很老的语言了,而且最让人叹惋的是,这语言一开始就饱受关注,然后就被广泛使用了,从此作出大的改动已经不太可能了。变量与作用域问题就是 Tcl 时代限制在这方面的体现。
17
2014
(lib)Tcl 现代方法:变量
之前有人问到如何从 C 端访问 Tcl 变量,此处做一总结。庶几不失「现代」之名。有关 Tcl_Obj 的维护者资料击此。
于是终于回到了主线。《Tcl 现代方法》本来是作为记录 Tcl 现代用法的系列博文,一开始是介绍 C 库的,但是后来 Tcl 脚本的内容反倒更多,结果现在纯粹谈起来 C 库又会导致歧义,因此在标题前加上 lib 标记,以示内容是 C 库而非 Tcl 脚本。
4
2014
Tcl 现代方法:你知道几种写类的方法?
本文是从底向上逐步构建其 TclOO 大框架的,如果你更喜欢自顶向上的,可以参考别的教程。
另外,本文只是入门级别,读完本文后再去看文档或者其他教程应该会容易些,毕竟是汉语写的。这里我推荐 Ashok 写的《Tcl Programming for Windows》中的 TclOO 一章。
除去协程,面向对象编程也是现代编程语言不可或缺的一部分。Tcl 在 8.6 之前都没有内建支持面向对象编程,但这不意味着 Tcl 没法 OO——恰恰相反,Tcl 有一大堆 OO 库,我随口就能叫出几个出名的:[incr Tcl]、XOTcl、Snit。这些库各有千秋,有的模仿 C++,有的是原型继承,还有的是模仿 Common Lisp Object System,千姿百态。可能和大家所想不同,这样的「大好」局势并未给 Tcl 带来许多好处:依然有人批评 Tcl 没有 OO 支持;有的人虽然知道有,但批评选择太多让用户无所适从,或者为自己所爱的库口诛笔伐;有的人虽然不在乎别人怎么选择,但很苦恼其他扩展包依赖了自己根本不需要的 OO 库……在这种情况下,Tcl Core Team 站了出来,提出了 TIP 257,由 Donal K. Fellows 主要实现。这套面向对象机制起名叫做 TclOO,并随 Tcl 本身提供。TclOO 的设计十分灵活,可以以此为基础重新制作 [incr Tcl] 等库,让大家其乐融融地生活在一起。
思考一下,开源系统的桌面环境是不是也是这样呢?
30
2014
Tcl 现代方法:TclHttpd 入门
TclHttpd 是 Tcl 界人尽皆知的有名软件,功能强大,易于使用。在其原作者不再维护之后,Cliff 和 Sean 于最近接手维护,使之支持最新的 8.6。
21
2014
Tcl 现代方法:eval 方法大全
#include <tcl.h>
/**
* puts [set a [expr {20 * 30}]
*/
void EvalString(Tcl_Interp *interp) {
Tcl_Obj *result;
char script[] = "set a [expr {20 * 30}]";
if (Tcl_Eval(interp, script) != TCL_OK) {
fprintf(stderr, "Error was: %s\n", Tcl_GetStringResult(interp));
return;
}
result = Tcl_GetObjResult(interp);
printf("%s\n", Tcl_GetStringFromObj(result, NULL));
}
/**
* puts [set a [expr {30 * 30}]]
*/
void EvalStringObj(Tcl_Interp *interp) {
Tcl_Obj *script;
Tcl_Obj *result;
script = Tcl_NewStringObj("set a [expr {30 * 30}]", -1);
Tcl_IncrRefCount(script);
Tcl_EvalObjEx(interp, script, 0);
result = Tcl_GetObjResult(interp);
printf("%s\n", Tcl_GetStringFromObj(result, NULL));
}
/**
* puts {hello world}
*/
void EvalListObj(Tcl_Interp *interp) {
Tcl_Obj *cmd;
cmd = Tcl_NewObj();
Tcl_ListObjAppendElement(interp, cmd, Tcl_NewStringObj("puts", -1));
Tcl_ListObjAppendElement(interp, cmd, Tcl_NewStringObj("hello world", -1));
Tcl_IncrRefCount(cmd);
Tcl_EvalObjEx(interp, cmd, 0);
Tcl_DecrRefCount(cmd);
}
/**
* puts [set a 32]
*/
void Eval(Tcl_Interp *interp) {
int i;
Tcl_Obj *scriptArr[3];
Tcl_Obj *resultObj;
int result;
scriptArr[0] = Tcl_NewStringObj("set", 3);
scriptArr[1] = Tcl_NewStringObj("a", 1);
scriptArr[2] = Tcl_NewIntObj(32);
for (i = 0; i < 3; ++i) {
Tcl_IncrRefCount(scriptArr[i]);
}
Tcl_EvalObjv(interp, 3, scriptArr, 0);
for (i = 0; i < 3; ++i) {
Tcl_DecrRefCount(scriptArr[i]);
}
resultObj = Tcl_GetObjResult(interp);
Tcl_IncrRefCount(resultObj);
Tcl_GetIntFromObj(interp, resultObj, &result);
Tcl_DecrRefCount(resultObj);
printf("%d\n", result);
}
int main(int argc, char *argv[]) {
Tcl_Interp *interp;
interp = Tcl_CreateInterp();
EvalString(interp);
EvalStringObj(interp);
EvalListObj(interp);
Eval(interp);
Tcl_DeleteInterp(interp);
return 0;
}