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++的关联。

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

  • 相关阅读:
    PAT (Advanced Level) 1010. Radix (25)
    PAT (Advanced Level) 1009. Product of Polynomials (25)
    PAT (Advanced Level) 1008. Elevator (20)
    PAT (Advanced Level) 1007. Maximum Subsequence Sum (25)
    PAT (Advanced Level) 1006. Sign In and Sign Out (25)
    PAT (Advanced Level) 1005. Spell It Right (20)
    PAT (Advanced Level) 1004. Counting Leaves (30)
    PAT (Advanced Level) 1001. A+B Format (20)
    PAT (Advanced Level) 1002. A+B for Polynomials (25)
    PAT (Advanced Level) 1003. Emergency (25)
  • 原文地址:https://www.cnblogs.com/helloWaston/p/4544846.html
Copyright © 2011-2022 走看看