免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1216 | 回复: 0
打印 上一主题 下一主题

OTcl与C++,NS2是如何识别并调用执行协议的 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-22 08:53 |只看该作者 |倒序浏览

/******************************************************

-------------------2007/09/25------------

-------------------author  hhj------------

******************************************************/

 http://blog.baisi.net/?uid-89519-action-viewspace-itemid-848

经过一段时间的代码阅读和资料查阅,在这里我想试着讲明一个困扰大 多数 NS2 Beginner 的问题: Otcl  C++ 的 交互,我们写的新协议(假若有的话)是如何被 NS2 执 行的。

就简单的从我们现有的来自长庚大学的 802.16 的补丁说起。移植完 16 的 补丁我们的 NS2 就可以执行 MAC 层 协议为“ Mac/802_16 “的 tcl 脚本代码。但是这个补丁( wimax_v2.03 )里面的代码全都是用 C++ 编 写的底层代码,在 tcl 脚本中设置 MAC 层 协议为 Mac/802_16  tcl 解 释器是如何正确的知道是执行我们的补丁呢?

这是 tcl 脚本中设置 16 协议 的地方:

set val(chan)   Channel/WirelessChannel    ;# channel type

set val(prop)   Propagation/TwoRayGround   ;# radio-propagation model

set val(netif)  Phy/WirelessPhy            ;# network interface type

set val(mac)    Mac/802_16                        ;# MAC type

             …………………………………………

            …………………………………………

$ns node-config -adhocRouting $val(rp) /

                 -llType $val(ll) /

                -macType $val(mac) /

            …………………………………………

            …………………………………………

 

我们打开 ns-2.29/mac/mac-802_16 下的 mac-802_16.cc 文件,翻看最后一段代码:

static class Mac802_16Class : public TclClass

{

public:

        // 构造函数 Mac802_16Class()  Otcl 中 的类名 Mac/802_16 作为参 数 传给其父类 TclClass 的构造函数

        // 要注意,这里实际上是创建了两个类: Mac  802_16 ,并且 802_16  Mac 的 子类;

       Mac802_16Class() : TclClass("Mac/802_16") {}

        //  create 方法则创建一个要与 Otcl 类对应的 C++ 类的对象实例,然后返回;

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

       {

              return (new Mac802_16());

       }

} class_mac802_16;

 

一个声明为 static 的类,在 NS2 初 始化的时候会调用该类的构造函数,在此 NS2 调用了Mac802_16Class  Mac802_16Class() ,这首先调用了 TclClass("Mac/802_16") 。我们接着翻看tclcl-1.17/Tcl.cc  TclClass() 是如何工作的。

 Tcl.cc 文件中 :

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

{

       if (Tcl::instance().interp()!=NULL) {

              // 如果 Otcl 语 言解释器已存在的话,调用 bind():

              // 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;

       }

}


往下 找到 bind() 

void TclClass::bind()

{

        // 获取 Tcl

       Tcl& tcl = Tcl::instance();

        //  Otcl 环境中注册该类名 :Mac802_16 ,其父类是 SpliteObject

              // 需要注意的是 :SpliteObject 存在于 otcl 环境中 ,  C++ 中的 TclObject 相对应

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

        // 注册了之后 , 为这个类添加两个命令 :create-shadow  delete-shadow ,注意:这两个命令的执行程序实际上就是 TclClass 类的 create_shadow()  TclClass::delete_shadow().

       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();

}

 

然后当我们在 ns 脚本中 :new Mac802_16 时,在 tclcl-1.17/tcl-object.tcl 中:

proc new { className args } {

     set o [SplitObject getid] 

           // 调 用了该类的 create 函数,即 Mac802_16: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 并没有实现 create() 函数!如何解决呢?我们往上找找看 SpliteObject 类是如何声明的: Class SpliteObject ,原来这实际上是调用了 Class  Create 函数:

 

Class instproc create() {

...

alloc();

init();

...

}

 

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

SplitObject instproc init args {

     $self next

 

          // 调用类的 create-shadow 函数,在这个例子中 , 就是 调用了 Mac802_16 instproc create_shadow 函数

          // 如前面所讲,也就是调用了 TclClass::create-shadow() 函数

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

         error "__FAILED_SHADOW_OBJECT_" ""

     }

}

 

我们继续翻看 TclClass  create_shadow() 函数,看它做了些什么:

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

{

     TclClass* p = (TclClass*)clientData;

          // 在这里调用了 Mac802_16Class::create() 函数,也就是调用了 C++ 环 境中的 :new Mac802_16 ,到这里为止 ,otcl 中的 Mac802_16 类对应的 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 中 的类 Mac802_16 添加两个命令: cmd  instvar ,其中 cmd 命 令是meet the Tcl Unknown mechanism —— Tcl  unknown 机制,这样一来 , 当你在 ns 脚本中输入了一个该类未知的命令, Tcl  unknown 机制就会调用该类的 cmd 命令,具体的过程可以翻看 NS 手册的相应部分,有比较详细的说明;

       //  cmd () 命令激活影像对象的 command() 方法,并将 cmd() 参数 以向量的形式传递给command() 方法,因此在实现某类的 C++ 部 分时 , 你必须实现该类的 Command() 过程,仔细看看NS2 中的大部分类,是不是都有一个 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);

     }

}

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP