国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
OTcl與C++NS2
經(jīng)過一段時(shí)間的代碼閱讀和資料查閱,在這里我想試著講明一個(gè)困擾大多數(shù)NS2 Beginner的問題:Otcl和C++的交互,我們寫的新協(xié)議(假若有的話)是如何被NS2執(zhí)行的。
就簡(jiǎn)單的從我們現(xiàn)有的來自長(zhǎng)庚大學(xué)的802.16的補(bǔ)丁說起。移植完16的補(bǔ)丁我們的NS2就可以執(zhí)行MAC層協(xié)議為“Mac/802_16“的tcl腳本代碼。但是這個(gè)補(bǔ)?。╳imax_v2.03)里面的代碼全都是用C++編寫的底層代碼,在tcl腳本中設(shè)置MAC層協(xié)議為Mac/802_16,tcl解釋器是如何正確的知道是執(zhí)行我們的補(bǔ)丁呢?
這是tcl腳本中設(shè)置16協(xié)議的地方:
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:
       //構(gòu)造函數(shù)Mac802_16Class()將Otcl中的類名Mac/802_16作為參數(shù)傳給其父類TclClass的構(gòu)造函數(shù);
       //要注意,這里實(shí)際上是創(chuàng)建了兩個(gè)類:Mac和802_16,并且802_16是Mac的子類;
      Mac802_16Class() : TclClass("Mac/802_16") {}
       //而create方法則創(chuàng)建一個(gè)要與Otcl類對(duì)應(yīng)的C++類的對(duì)象實(shí)例,然后返回;
      TclObject* create(int, const char*const*)
      {
             return (new Mac802_16());
      }
} class_mac802_16;

一個(gè)聲明為static的類,在NS2初始化的時(shí)候會(huì)調(diào)用該類的構(gòu)造函數(shù),在此NS2調(diào)用了Mac802_16Class:Mac802_16Class(),這首先調(diào)用了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語言解釋器已存在的話,調(diào)用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環(huán)境中注冊(cè)該類名:Mac802_16,其父類是SpliteObject
             //需要注意的是:SpliteObject存在于otcl環(huán)境中,與C++中的TclObject相對(duì)應(yīng)
      tcl.evalf("SplitObject register %s", classname_);
       //注冊(cè)了之后,為這個(gè)類添加兩個(gè)命令:create-shadow和delete-shadow,注意:這兩個(gè)命令的執(zhí)行程序?qū)嶋H上就是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();
}
然后當(dāng)我們?cè)趎s腳本中:new Mac802_16時(shí),在tclcl-1.17/tcl-object.tcl中:

proc new { className args } {

    set o [SplitObject getid]

         //調(diào)用了該類的create函數(shù),即Mac802_16:create()函數(shù),也就是調(diào)用了其父類SpliteObject:create()函數(shù)

        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

}



但是問題出現(xiàn)了:實(shí)際上SpliteObject并沒有實(shí)現(xiàn)create()函數(shù)!如何解決呢?我們往上找找看SpliteObject類是如何聲明的:Class SpliteObject,原來這實(shí)際上是調(diào)用了Class的Create函數(shù):



Class instproc create() {

...

alloc();

init();

...

}



這就會(huì)調(diào)用SpliteObject instproc init()函數(shù)

SplitObject instproc init args {

    $self next



         //調(diào)用類的create-shadow函數(shù),在這個(gè)例子中,就是調(diào)用了Mac802_16 instproc create_shadow函數(shù)

         //如前面所講,也就是調(diào)用了TclClass::create-shadow()函數(shù)

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

        error "__FAILED_SHADOW_OBJECT_" ""

    }

}



我們繼續(xù)翻看TclClass的create_shadow()函數(shù),看它做了些什么:

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

{

    TclClass* p = (TclClass*)clientData;

         //在這里調(diào)用了Mac802_16Class::create()函數(shù),也就是調(diào)用了C++環(huán)境中的:new Mac802_16,到這里為止,otcl中的Mac802_16類對(duì)應(yīng)的shadow object(影象對(duì)象)就生成了

    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添加兩個(gè)命令:cmd和instvar,其中cmd命令是meet the Tcl Unknown mechanism——Tcl的unknown機(jī)制,這樣一來,當(dāng)你在ns腳本中輸入了一個(gè)該類未知的命令,Tcl的unknown機(jī)制就會(huì)調(diào)用該類的cmd命令,具體的過程可以翻看NS手冊(cè)的相應(yīng)部分,有比較詳細(xì)的說明;

     //而cmd()命令激活影像對(duì)象的command()方法,并將cmd()的參數(shù)以向量的形式傳遞給command()方法,因此在實(shí)現(xiàn)某類的C++部分時(shí),你必須實(shí)現(xiàn)該類的Command()過程,仔細(xì)看看NS2中的大部分類,是不是都有一個(gè)Command()函數(shù)?其實(shí)就是這么來的

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

    }

}
command()這個(gè)函數(shù)實(shí)現(xiàn)所有的命令分發(fā),下面摘抄手冊(cè)的一部分來說明command()的定義(ASRMAgent::command()為例):

--------------------------------------------------------------------------------------------------------

int ASRMAgent::command(int argc, const char*const*argv) {

    Tcl& tcl = Tcl::instance();

    if (argc == 3) {

          if (strcmp (argv[1],"distance?") == 0) {

                int sender = atoi (argv[2]);

                SRMinfo* sp = get_state(sender);

                tcl.tesultf("%f", sp->distance_);

                return TCL_OK;

          }

                                             12

        }

        return (SRMAgent::command(argc,argv));

    }



          函數(shù)調(diào)用時(shí)需要兩個(gè)參數(shù):argc和argv,第一個(gè)參數(shù)(argc)代表解釋器中該行命令說明的參數(shù)個(gè)數(shù)。

          命令行向量(argv)包括:

             ——argv[0]為方法的名字,"cmd"。

             ——argv[1]為所要求的操作。

             ——如果用戶還有其他特殊的參數(shù),                 他們就被放在argv[2...(argc-1)]。

          參數(shù)是以字符串的形式傳遞的;他們必須被轉(zhuǎn)換成適合的數(shù)據(jù)形式。

          如果操作成功匹配,將通過前面(3.3.3)的方法返回操作的結(jié)果。

          command()必須以TCL_OK或TCL_ERROR作為函數(shù)的返回代碼,來

          表明成功或者失敗。

          如果操作在這個(gè)方法中沒有找到匹配的,它將調(diào)用其父類的command

          方法,同時(shí)也就返回相應(yīng)的結(jié)果。

          這就允許用戶創(chuàng)建和對(duì)象過程或編譯方法一樣層次特性的操作。

          當(dāng)command方法是為多繼承的類定義時(shí),程序員可以自由的選擇其中

          一個(gè)實(shí)現(xiàn);

        1)可以調(diào)用其中一個(gè)的父command方法,然后返回其相應(yīng)的結(jié)構(gòu),或

        2)可以以某種順序依次調(diào)用每一個(gè)的父command方法,然后返回第一個(gè)

        調(diào)用成功的結(jié)果。如果沒有調(diào)用成功的,將返回錯(cuò)誤。

        在我們這個(gè)文件里,我們把通過command()執(zhí)行的操作叫做準(zhǔn)成員函數(shù),這個(gè)名字反映了這些操作作為一個(gè)對(duì)象的OTcl實(shí)例過程的用途。

-------------------------------------------------------------------------------------------------------------------

我想講到這里大概可以明白開篇所說的:“我們寫的新協(xié)議(假若有的話)是如何被NS2執(zhí)行的”了,但是,假若你不想弄的太明白,那么你只需要了解以下實(shí)事:

如果我們要往NS2中添加自己的模塊,那么我們至少要實(shí)現(xiàn)兩個(gè)類:

一,首先要有一個(gè)類繼承自TclObject類或者其子類,例如這個(gè)Mac802_16類的繼承關(guān)系為:TclObject/NsObject/Mac/Mac802_16.這個(gè)類里面實(shí)現(xiàn)了C++類里面的變量與Otcl類的變量的綁定關(guān)系,以及我們的模塊要實(shí)現(xiàn)的一系列算法等等,這個(gè)類負(fù)責(zé)的就是協(xié)議的實(shí)現(xiàn)。

這個(gè)類,一般需要有構(gòu)造函數(shù)中執(zhí)行變量的綁定,使用bind()函數(shù),將Otcl變量與C++的成員變量綁定起來。

聲明為protected的command()函數(shù):為Otcl類提供方法,對(duì)Otcl中的類的方法進(jìn)行翻譯并執(zhí)行;對(duì)于沒有考慮到的或者不能解析的命令,調(diào)用該C++類的父類的command方法。當(dāng)在Otcl類中調(diào)用某個(gè)方法時(shí),首先去tcl類中查找并執(zhí)行該方法;若查找失敗,則在該Otcl類對(duì)應(yīng)的C++類的command方法中查找,若查找仍然失敗,則沿著該類的父類一直往上找,嘗試調(diào)用它們的command方法;若所有父類的command方法都不能解析,則報(bào)告該命令無法執(zhí)行。

其他的成員變量和成員函數(shù),這是用于實(shí)現(xiàn)自己的算法模塊的內(nèi)容。

二,其次我們要定義一個(gè)聲明為static的類,繼承自TclClass類,這個(gè)類實(shí)現(xiàn)了C++環(huán)境里面的類與Otcl環(huán)境里面的類的關(guān)聯(lián),簡(jiǎn)單點(diǎn)來說,這個(gè)類負(fù)責(zé)與Otcl環(huán)境進(jìn)行關(guān)聯(lián)。取最開頭的那段代碼;

static class Mac802_16Class : public TclClass

{

public:

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

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

      {

             return (new Mac802_16());

      }

} class_mac802_16;

這一段代碼里面,包含了一個(gè)將Otcl的類名作為參數(shù)傳給其父類的構(gòu)造函數(shù);一個(gè)create方法:創(chuàng)建一個(gè)C++類的對(duì)象實(shí)例并返回;該方法的返回類定定義為TclObject*。C++類的類型包含在create方法中,Otcl類的類型包含在TclClass類的構(gòu)造函數(shù)中,因此可以實(shí)現(xiàn)C++類和Otcl類的連接。



接下來,如果我們要實(shí)現(xiàn)的類完成以后,將頭文件和源文件放置于~ns目錄下自己新建的一個(gè)子目錄,然后打開~ns/Makefile文件,將“類名.o”添加到該Makefile的OBJ_CC宏定義中,對(duì)ns進(jìn)行編譯的時(shí)候就能夠能夠找到該模塊的源文件并將其編譯到ns中;如果類中定義了一些變量,打開~ns/tcl/lib/ns-default.tcl文件,為該類對(duì)應(yīng)的Otcl類設(shè)置一些初始值。最后,對(duì)Makefile執(zhí)行指令:make clean,make,對(duì)整個(gè)ns重新編譯,我們的模塊就可以添加到ns2中了。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
NS2中添加OTcl與C++之間的連接
Making NS-2 simulate an 802.11b link
ubuntu下安裝ns2詳細(xì)步驟
NS2和OPNET的討論
用PHP實(shí)現(xiàn)通過Web執(zhí)行C/C++程序
關(guān)于int main(int argc,char *argv[])的問題[轉(zhuǎn)](僅參考 不全)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服