转自:http://blog.sina.com.cn/s/blog_af68a2c201014nxq.html
(1)NS2中的网络构件一般由相互关联的两个类来实现,一个在C++中,一个在OTcl中,这种方式称为分裂对象模型。
注:解释类指的是OTcl中的类,编译类指的是对应的C++中的类
(2)OTcl类能够直接调用C++类函数,之间能够互相操作对方定义的数据,并且两类可以对应起来,OTcl和C++的分层结构也是一致的,此种机制称为---TclCL===OTcl C++ Linkage。
----------------|--------------------------
----OTcl-----对-|--应-------C++------------
----------------|--------------------------
(3)NS-2中所有的OTcl类的基类是SplitObject,而对应的所有C++的类的基类是TclObject。
(4)TclCL机制中定义了6个类---p185《1》
其中重要的有2个
TclCL主要通过这两个类TclClass和TclObject实现OTcl和C++类之间的关联
Tcl-----封装了OTcl解释器的实例,通过解释器实例提供了C++对象访问Tcl库函数的接口;《2》p53-解释器实例的相关操作。
TclClass-----封装了C++和OTcl的映像机制,关联,具有两个重要的功能:
(1) 为C++类和OTcl类建立关联(TclClass类的构造函数)和初始化TclObject类的成员方法(OTcl中的cmd过程和C++中的command函数);
(2) 每个C++类都有一个TclClass类派生来的静态类,该类的create函数接收OTcl基类传来的参数名(类名);创建相应的C++对象,并返回相应的指针;
TclObject-----C++所有类(编译类)的最高基类,对应SplitObject是OTcl所有类(解释类)的基类。
(1) 创建和销毁解释对象---在ns2中执行操作new{}和delete{}的创建和销毁解释对象的时候,会调用对应编译对象的对应过程创建和销毁影响对象《2》p55
(2) 变量绑定---(位置)是在编译对象的构造函数中实现的,(类型)不通类型的数据具有不同的赋值语法,(绑定方法)bind()函数
(3) C++和OTcl之间函数方法的对应-----每个解释对象都有一个cmd{}过程,以及每个编译对象的Command()函数,,前者自动调用后者的对应部分以实现成员函数的调用 《2》p57 《1》p187-p188
command函数的参数
argc表示参数个数,
argv参数数组,argv[0]方法名:cmd,--表明是otcl脚本通过cmd过程传递过来的操作
argv[1]---otcl中执行的操作的名字
argv[n]---其他的参数。
TclComand-----略
EmbeddedTcl---略
Instvar---略
(5)综上,如果想要在NS-2中添加自己的模块,至少需要实现2个类:继承自TclObjectl类的子类(实现算法);继承自TclClass类的Static的类(用于关联)。《2》p65
(6)具体实例:具体的细节描述可以结合《2》p52—p59 基本都可以查到
1, C++类到OTcl类的映射
C++类到OTcl类的映射是指在用Tcl语言进行仿真时,使用诸如"new Agent/MyAgentOtcl"命令生成OTcl对象,NS2将要生成的对应的C++对象。这个"new Agent/MyAgentOtcl"对应的是解释类(interpreted classes),而它对应的C++类称为编译类(compiled classes)。
这种类的映射是通过在C++程序中继承纯虚类TclClass实现的。设我们用C++设计一个MyAgent类,那么为了在仿真时用OTcl语言得到一个它的对象,我们需要的就是:
用MyAgentClass继承一下TclClass,并在其中的create()函数中返回一个MyAgent()的对象。这样我们在OTcl语言中写下"new Agent/MyAgentOtcl"时,NS2就会找到C++类MyAgentClass,执行其中的create()函数,而这个函数返回一个MyAgent类的对象,于是就在OTcl语言中生成了一个C++类的影子对象(shadow object),完成了映射。
2,C++类与OTcl类的变量绑定
在仿真过程中经常需要设定对象的参数,如node的配置、agent的速率等,这些对OTcl对象的参数设定需要被映射到C++对象才算是真正起到了作用。这种绑定是通过在类的构造函数中使用bind()函数实现的:
第一个形参就是OTcl对象中将要使用的变量名,第二个形参是C++类中的变量名。这就完成了my_var和my_var_otcl之间的绑定。
3,C++类的操作到OTcl对象的操作的映射
OTcl对象进行的操作是通过对应的C++类中实现的command()函数定义的,比如:
这样在OTcl中写出
set myagent [new Agent/MyAgentOtcl]
$myagent call-my-priv-func
第一条命令是通过1中讲过的类的映射实现的,生成了一个MyAgent对象myagent;第二条命令调用了MyAgent类的command()函数中对应"call-my-priv-func"字段部分的操作。这就实现了C++类中的操作到OTcl对象的映射。
4,OTcl类的操作到C++类的操作的映射
在C++设计中也会用到OTcl类给出的一些操作,如:
就是在MyAgent类中生成了一个Tcl对象tcl(解释器对象),并调用了tcl的几个函数打印一些信息。通过将MyAgent类映射到OTcl类,在仿真中我们就可以看到NS2打印出的提示信息。