最近几天,对ns2进行研究,ns2为什么要使用两种语言,因为C++执行速度快,因此对于一些不需要经常改变的东西:例如包的发送。而对于需要经常进行修改的就不能够使用C++,而使用OTcl脚本语言。所有OTcl的基类是SplitObject。

首先,在otcl中new一个对象的时候,会调用tclcl/tcl-object.tcl中的proc new

代码如下:

proc new { className args } {
set o [SplitObject getid]
if [catch "$className create $o $args" msg] {
if [string match "__FAILED_SHADOW_OBJECT_" $msg] {
#
# The shadow object failed to be allocated.

delete $o
return ""
}
global errorInfo
error "class $className: constructor failed: $msg" $errorInfo
}
return $o
}

从这个函数中可以看到,调用了creat方法,(create方法生成一个新的类和对象)。

生成的对象会调用构造函数,$self next,调用父类的构造函数(otcl中构造函数书init()),最终调用SpliteObject中的init()方法。代码:

SplitObject instproc init args {
$self next
if [catch "$self create-shadow $args"] {
error "__FAILED_SHADOW_OBJECT_" ""
}
}

这个方法会调用creat-shadow方法,这个方法在TclClass(tclcl/Tcl.cc)中,我们先来看下create-shadow方法:

int TclClass::create_shadow(ClientData clientData, Tcl_Interp *interp,
   int argc, CONST84 char *argv[])
{

TclClass* p = (TclClass*)clientData;
TclObject* o = p->create(argc, argv);

tcl.enter(o);

enter是将tclObject放到hash表中,即在生成TclObject的时候就将这个对象放到TCL类中hash表中。

为了弄清楚create方法干什么我们看下下面这段代码:

 static
class RenoTcpClass: public TclClass {
    public:
    RenoTcpClass() : TclClass("Agent/TCP/Reno") {}
    TclObject* create(int argc, const char*const* argv) {
    return (new RenoTcpAgent());
    }
    } class_reno;

从这个可以看到RenoTcpClass
中的create方法 返回TclObject对象,然而首先调用RenoTcpClass的构造函数

这个会调用TclClass的构造函数。

TclClass::TclClass(const char* classname) : class_(0),
classname_(classname)
{
if (Tcl::instance().interp()!=NULL) {
// the interpreter already exists!
// this can happen only (?) if the class is created as part
// of a dynamic library

bind();
} else {
// the interpreter doesn't yet exist
// add this class to a linked list that is traversed when
// the interpreter is created

next_ = all_;
all_ = this;
}
}

从上可知道,如果tcl解释器生成,则调用bind()。bind:

void TclClass::bind()
{
Tcl& tcl = Tcl::instance();
tcl.evalf("SplitObject register %s", classname_);
class_ = OTclGetClass(tcl.interp(), (char*)classname_);
OTclAddIMethod(class_, "create-shadow",
      (Tcl_CmdProc *) create_shadow, (ClientData)this, 0);
OTclAddIMethod(class_, "delete-shadow",
      (Tcl_CmdProc *) delete_shadow, (ClientData)this, 0);
otcl_mappings();
}

这个会调用splitObject对象的register方法,就是对

SplitObject proc register className {
set classes [split $className /]
set parent SplitObject
set path ""
set sep ""
foreach cl $classes {
set path $path$sep$cl
if ![$self is-class $path] {
Class $path -superclass $parent
}
set sep /
set parent $path
}
}

这样就是OTcl类的注册。差不多完成了Otcl和C++的关联。

本人也是初学者,有什么问题,希望提出,然后进行修改。

最新文章

  1. bzoj1251
  2. Hawk使用补充说明
  3. 推荐15款制作 SVG 动画的 JavaScript 库
  4. 关于jQuery源码分析
  5. iPad 2升级iOS 9的过程记录
  6. WCF配置文件全攻略
  7. js定时显示广告代码
  8. sun.misc.BASE64Encoder是内部专用 API, 可能会在未来发行版中删除
  9. DropDownList单选与多选下拉框
  10. Linux Ubuntu jdk(环境变量)配置
  11. js获取元素位置和style的兼容性写法
  12. 背水一战 Windows 10 (82) - 用户和账号: 获取用户的信息, 获取用户的同意
  13. python数据探索
  14. Linux 下 wordpress 无法安装插件
  15. KNN算法原理(python代码实现)
  16. 如何取得Oracle并行执行的trace
  17. linux下每次git clone不需输入账号密码的方法
  18. Fiddler HTTPS抓包
  19. 一个几百行代码实现的http服务器tinyhttpd
  20. juniper ssg 常用命令

热门文章

  1. 【xlwings1】Python-Excel 模块哪家强
  2. warning: deprecated conversion from string constant to 'char*
  3. ModelAndView返回mav时,报404
  4. MyBatis 动态sql标签trim
  5. composer本地安装文档 - CSDN博客
  6. Data Lake Analytics IP白名单设置攻略
  7. HR招聘_(三)_招聘方法论(招聘途径及流程)
  8. web前端学习(二)html学习笔记部分(3)--range对象
  9. LintCode_133 最长单词
  10. 实现移动端上拉加载和下拉刷新的vue插件(mescroll.js)