真正实现精确创建影像的TclClass(~/tclcl1.17/tcl.cc)

http://hi.baidu.com/jacktar11/blog/item/4b0f25ece4cbcf20adafd51b.html

 

所添加的新协议的C++文件中都会有一段代码 eg:

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

 

//在这里再次为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);

}

}

command()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值