OTcl与C++交互—AODV路由协议

我们先来看看Otcl脚本:

set val(chan)       Channel/WirelessChannel      ;#无线信道类型
set val(prop)       Propagation/TwoRayGround     ;#无线传输模型
set val(netif)      Phy/WirelessPhy              ;#网络接口类型
set val(mac)        Mac/802_11                   ;#MAC层协议
set val(ifq)        Queue/DropTail/PriQueue      ;#队列接口类型
#set val(ifq)       CMUPriQueue                  ;#队列接口类型,DSR协议
set val(ll)         LL                           ;#逻辑链路层类型
set val(ant)        Antenna/OmniAntenna          ;#天线模型
set val(adhocRouting)   AODV                     ;#无线路由协议
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
#配置无线节点
$ns_ node-config -adhocRouting $val(adhocRouting) \
                 -llType $val(ll) \
                 -macType $val(mac) \
                 -ifqType $val(ifq) \
                 -ifqLen $val(ifqlen) \
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

上面的代码描述了无线节点会通过AODV路由协议来进行配置,现在看看AODV路由协议是怎么执行的。在aodv.cc中:

static class AODVclass : public TclClass {
public:
        AODVclass() : TclClass("Agent/AODV") {} //构造函数调用其基类的构造函数
        TclObject* create(int argc, const char*const* argv) {
          assert(argc == 5);
          //return (new AODV((nsaddr_t) atoi(argv[4])));
//返回一个新建的编译类的实例对象
	  return (new AODV((nsaddr_t) Address::instance().str2addr(argv[4])));
        }
} class_rtProtoAODV;
类AODVclass实际上只有两个函数:构造函数和creat()函数。构造函数AODVclass()实际上调用了其父类TclClass的构造函数,并且传递了Agent/AODV作为参数。接下来看看TclClass是如何工作的:
TclClass::TclClass(const char* classname) : class_(0), classname_(classname)
{
	if (Tcl::instance().interp()!=NULL) {//如果解释器存在
				bind();
	} else {
		
		next_ = all_;
		all_ = this;
	}
}

下面看看bind()函数是如何执行的:

void TclClass::bind()
{
	Tcl& tcl = Tcl::instance();
//在Otcl环境中注册类名:Agent/AODV。其父类是SplitObject
	tcl.evalf("SplitObject  register %s", classname_);
	class_ = OTclGetClass(tcl.interp(), (char*)classname_);
//这两行代码实际上是为这个类创建了create-shadow和delete-shadow这两个命令
// create-shadow是创建OTcl影像类的命令
	OTclAddIMethod(class_, "create-shadow",
		       create_shadow, (ClientData)this, 0);
	OTclAddIMethod(class_, "delete-shadow",
		       delete_shadow, (ClientData)this, 0);
	otcl_mappings();
}

此时我们已经在OTcl环境中注册了OTcl类:Agent/AODV。但是对应于Otcl解释类的编译类还没有被构造,并且也没有被关联。

当我们在OTcl脚本中使用AODV配置节点时,会创建一个OTcl解释类对象实例,这就会调用tclcl-1.15\tcl-object.tcl中的new过程

proc new { className args } {
	set o [SplitObject getid]
	if [catch "$className create $o $args" msg] {//调用了该类的creat函数
		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函数,实际上是调用了Agent/AODV:creat(),实际上也是调用了其父类SplitObject的creat()函数,SplitObject实际上没有creat()函数,它调用了Classcreate()函数

Class instproc create {obj args} {              
  set h [$self info heritage]                   
  foreach i [concat $self $h] {                 
    if {[$i info commands alloc] != {}} then {  
      set args [eval [list $i] alloc [list $obj] $args]       
      $obj class $self                          
      eval [list $obj] init $args   ;#调用了init过程                   
      return $obj                               
    }                                           
  }                                             
  error {No reachable alloc}                    
}
这实际上又调用了SplitObject的init()函数
SplitObject instproc init args {
	$self next
	if [catch "$self create-shadow $args"] {
		error "__FAILED_SHADOW_OBJECT_" ""
	}
}
这实际上调用了Agent/AODV 的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& 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());
//在这里添加了两个命令:cmd和instvar。
		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);
	}
}

cmd()命令激活影像对象的command()方法,并将cmd()的参数以向量形式传递给command()方法,因此此函数必须实现,其用途就是用来接收cmd()传递的OTcl命令。








转载于:https://www.cnblogs.com/yue-/archive/2012/06/10/6260054.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值