【NS2】ns2 otcl与c++关联(转载)

最近几天,对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++的关联。

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

posted @ 2015-06-01 20:40  HelloWaston  阅读(360)  评论(0编辑  收藏  举报