zoukankan      html  css  js  c++  java
  • 【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++的关联。

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

  • 相关阅读:
    [转]WebForm中使用MVC
    [转]外贸出口流程图
    [转]查看SQL Server被锁的表以及如何解锁
    [转]RDL Report in Visual Studio New page per Record
    [转]Sql Server Report Service 的部署问题
    [转]ASP.NET MVC4中@model使用多个类型实例的方法
    [转]告别写计划的烦恼!一页纸四步打造出一份牛逼的商业计划
    [转]LINQ: Using INNER JOIN, Group and SUM
    [转] 比特币『私钥』『公钥』『钱包地址』间的关系
    [转]SQL SERVER数据库删除LOG文件和清空日志的方案
  • 原文地址:https://www.cnblogs.com/helloWaston/p/4544846.html
Copyright © 2011-2022 走看看