NS2的运行机制

详细讲解NS2运行机制

转载自:http://blog.csdn.net/kgn28/article/details/3058810

ns2中,每一个类都有一个Otcl类和一个c++类,每个需要交互的c++类都有一个“链接类(该类包括一个方法,该方法实例化一个指定的类并且返回一个指向该实例的一个指针)”,该“链接类”通过其父类的构造方法在编译阶段注册一个方法到TclLinkage(otcl类可以找到并且可以调用该方法),这样在Otcl类初始化一个一个类的时候,调用之前注册过的方法,就可以初始化一个c++类了,并且还会注册一个使得Otcl类可以调用c++的类的方法——通过顺序查找实现的。这样以后在Otcl类就可以调用c++类中的方法了,说的有点乱,但是如果你看过一个例子,就会觉得我说的有道理了。

还是调用网上某位高手的一个例子吧,在这里我就补充说明一下tcl的unknown机制。

static class ChannelClass : public TclClass {

public:

     ChannelClass() : TclClass("Channel") {}

     TclObject* create(int, const char*const*) {

         return (new Channel);

     }

} class_channel

 

当ns instantiating the class_channel object时,它会invoke ChannelClass:ChannelC

 

lass();

这会首先invoke TclClass:TclClass("Channel");

 

在Tcl.cc文件中:

TclClass::TclClass(const char* classname) : class_(0), classname_(classname)

{

         #如果Otcl语言解释器已存在的话:

         bind();

}

 

void TclClass::bind()

{

          #首先获取Tcl

     Tcl& tcl = Tcl::instance();

 

          #在Otcl环境中注册该类名:Channel

          #并且该类的父类是SpliteObject

          #Note:SpliteObject存在于otcl环境中,与C++中的TclObject相对应

          tcl.evalf("SplitObject register %s", classname_);

 

          #注册了之后,为这个类添加两个命令:create-shadow和delete-shadow

          #Note:the implementation procedures of these two methods就是

          #TclClass::create_shadow()和TclClass::delete_shadow().

          class_ = OTclGetClass(tcl.interp(), (char*)classname_);

          OTclAddIMethod(class_, "create-shadow",

                create_shadow, (ClientData)this, 0);

          OTclAddIMethod(class_, "delete-shadow",

                delete_shadow, (ClientData)this, 0);

          otcl_mappings();

}

 

然后当你在ns环境中敲入:new Channel时

 

在文件tcl-object.tcl中:

proc new { className args } {

     set o [SplitObject getid]

 

          #调用了该类的create函数,即Channel:create()函数

          #也就是调用了SpliteObject:create()函数

         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

}

 

但是SpliteObject并没有implement create() 函数,

但是你别忘了在otcl环境中,SpliteObject类是这样声明的:Class SpliteObject

所以这会调用Class的Create函数

 

Class instproc create() {

...

alloc();

init();

...

}

 

这就会调用SpliteObject instproc init()函数

SplitObject instproc init args {

     $self next

 

          #调用类的create-shadow函数

          #在这个例子中,就是调用了Channel instproc create_shadow函数

          #也就是调用了TclClass::create-shadow()函数,因为在之前的bind()方法中有将这两种操作对应起来。

     if [catch "$self create-shadow $args"] {

         error "__FAILED_SHADOW_OBJECT_" ""

     }

}

 

int TclClass::create_shadow(ClientData clientData, Tcl_Interp *interp,

                 int argc, char *argv[])

{

     TclClass* p = (TclClass*)clientData;

 

          #在这里调用了ChannelClass::create()函数

          #也就是调用了C++环境中的:new Channel

          #到这里为止,otcl中的Channel的shadow object就生成了

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

     Tcl& tcl = Tcl::instance();

     if (o != 0) {

         o->name(argv[0]);

         tcl.enter(o);

         if (o->init(argc - 2, argv + 2) == TCL_ERROR) {

             tcl.remove(o);

             delete o;

             return (TCL_ERROR);

         }

         tcl.result(o->name());

 

                 #在这里再次为otcl中的类Channel添加两个instproc:cmd和instvar

                 #其中cmd命令是meet the Tcl Unknown mechanism

(如果有同名的tcl方法就调用该方法,如果没有该方法当然是unknown了。

                 #这样的话,当你在ns脚本中输入了一个该类未知的命令,

                 #Tcl的unknown机制就会调用该类的cmd命令

#在/tclcl/tcl-object.tcl中

SplitObject instproc unknown args {

    if [catch "$self cmd $args" ret] {

        set cls [$self info class]

        global errorInfo

        set savedInfo $errorInfo

        error "error when calling class $cls: $args" $savedInfo

    }

    return $ret

}

                #而这进一步的就会调用该类的shadow object的command()过程

                 #所以在实现类的C++部分时,你必须实现该类的Command()过程

                 #在command()中实现所有的命令分发

         OTclAddPMethod(OTclGetObject(interp, argv[0]), "cmd",

                    dispatch_cmd, (ClientData)o, 0);

         OTclAddPMethod(OTclGetObject(interp, argv[0]), "instvar",

                    dispatch_instvar, (ClientData)o, 0);

         o->delay_bind_init_all();

         return (TCL_OK);

     } else {

         tcl.resultf("new failed while creating object of class %s",

                 p->classname_);

         return (TCL_ERROR);

     }

}

通过上面的例子可以了解到Otcl可以调用c++类中的方法,而c++中的类可不可以调用Otcl类中的方法呢,答案是可以的,是通过得到一个Tcl实例来实现的,具体请参考everything.pdf里面有详细的介绍(其实我总解的这些也是通过在总结一下学习该文档的经验而已,这个文档真的可以称得上是everything了,包括了ns2的一切内容,就是太长了)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值