解释器的接口代码在单独的tclcl目录下,其他模拟器代码在ns-2目录下。
~tclcl里面定义了很多类,ns中使用的有6个:
Tcl,TclObject,TclClass,TclObject,TclCommand,EmbeddedTcl,InstVar
首先总结学习下Tcl类。
文件:~tclcl/tcl.cc;ns-allinone-2.33/include/tcl.h
用途:包含了C++代码将要用来访问解释器的方法。
方法:
(1)获取Tcl类实例的指针。
Tcl& tcl=Tcl::instance();
必须获取一个这个实例的指针,以访问其他的方法。
(2)调用OTcl过程。
有四种方法。 -------C++类调用Otcl
执行过程: 每个函数都传递一个字符串(string)给解释器,然后解释器通过一个全局文本来识别这个字符串。如果解释器返回TCL_OK,则这些函数将会返回一个相应的OTcl过程。反过来,如果解释器返回TCL_ERROR,则这些函数将调用tkerror{}。用户可以重载(overload)这个过程,以便有选择地忽略某些类型的错误。
四种方法:
●tcl.eval(char* s) 调用Tcl_GlobalEval(),通过解释器执行s。
●tcl.evalc(const char* s) 保存字符串参数s。它将字符串s复制到中间缓冲区;然后再在中间缓冲区里面调用之前的eval(char* s)。
●tcl.eval() 假设命令已经存储在internal bp_类中;它直接调用tcl.eval(char* bp_)。缓冲区自己的指针可以通过tcl.buffer(void)方法获得。
●tcl.evalf(const char* s, . . . ) 类似于一个Printf(3)。它在内部使用vsprintf(3)来创建输入的字符串。
例子:
Tcl& tcl = Tcl::instance();
char wrk[128];
strcpy(wrk, "Simulator set NumberInterfaces_ 1");
tcl.eval(wrk);
sprintf(tcl.buffer(), "Agent/SRM set requestFunction_ %s", "Fixed");
tcl.eval();
tcl.evalc("puts stdout hello world");
tcl.evalf("%s request %d %d", name_, sender, msgid);
(3)从解释器传出或传入结果
中间媒介:私有成员变量tcl_->result
a.解释器调用C++方法。
C++方法使用tcl.result(const char* s), tcl.resultf(const char* fmt, . . . )设置tcl_->result,并将结果字符串返回给解释器。
例子:
if (strcmp(argv[1], "now") == 0) {
tcl.resultf("%.17g", clock());
return TCL_OK;
}
tcl.result("Invalid operation specified");
return TCL_ERROR;
b.C++方法调用Otcl命令。
解释器返回结果到tcl_->result。tcl.result(void)必须用于取回结果。
例子:
tcl.evalc("Simulator set NumberInterfaces_");
char* ni = tcl.result();
if (atoi(ni) != 1)
tcl.evalc("Simulator set NumberInterfaces_ 1");
(4)错误报告与退出
tcl.error(const char* s)执行:将s写入stdout;将tcl_->result写入stdout;退出,并将错误代码(error code)置1。
注意:返回TCL_ERROR---tcl.h中定义和Tcl::error()---tcl.cc中定义的区别(28页)
(5)解释器内的Hash函数
tcl.enter(TclObject* o)将在hash表插入一个指向TclObject o的指针(pointer)。它被TclClass::create_shadow()用来在对象建立时,将其插入表中。
tcl.lookup(char* s)将取回名为s的TclObject。可以这样被使用:TclObject::lookup()。
tcl.remove(TclObject* o)将删除hash表中TclObject o的指针。可以用TclClass::delete_shadow()来移出hash表中存在的入口,此时该对象已经被删除。
这些函数是在TclObject类和TclClass类内部被使用的。
(6)解释器上的其他操作 :获得解释器句柄,用来编写我们自己的函数。
tcl.interp(void)返回一个解释器的handle,并存储在Tcl类中。
http://blog.csdn.net/tiaohua/article/details/4644620