📄 otcl.tex
字号:
\begin{program} new Trace "X"\end{program}Finally, the nitty-gritty details of how the interpreted class hierarchy is constructed:\begin{enumerate}\item The object constructor is executed when \ns\ first starts.\item This constructor calls the TclClass constructor with the name of the interpreted class as its argument.\item The TclClass constructor stores the name of the class, and inserts this object into a linked list of the TclClass objects.\item During initialization of the simulator, \fcnref{\fcn{Tcl\_AppInit}}{../ns-2/ns_tclsh.cc}{::Tcl\_AppInit} invokes \fcnref{\fcn{TclClass::bind}}{../Tcl/Tcl.cc}{TclClass::bind}\item For each object in the list of TclClass objects, \fcn[]{bind} invokes \fcnref{\proc[]{register}}{../Tcl/tcl-object.tcl}{TclObject::register}, specifying the name of the interpreted class as its argument.\item \proc[]{register} establishes the class hierarchy, creating the classes that are required, and not yet created.\item Finally, \fcn[]{bind} defines instance procedures \code{create-shadow} and \code{delete-shadow} for this new class.\end{enumerate}\section{Class TclCommand}\label{sec:TclCommand}This class (\clsref{TclCommand}{../Tcl/Tcl.h})provides just the mechanism for \ns\ to exportsimple commands to the interpreter, that can then be executed within a global context by the interpreter.There are two functions defined in \nsf{misc.cc}:\code{ns-random} and \code{ns-version}.These two functions are initialized by the function\fcnref{\fcn{init\_misc}}{../ns-2/misc.cc}{::init\_misc},defined in \nsf{misc.cc};\code{init_misc} is invoked by\fcnref{\fcn{Tcl\_AppInit}}{../ns-2/ns_tclsh.cc}{::Tcl\_AppInit}during startup.\begin{itemize}\itemsep0pt\item \clsref{VersionCommand}{../ns-2/misc.cc} defines the command \code{ns-version}. It takes no argument, and returns the current \ns\ version string.\begin{program} % ns-version \; get the current version; 2.0a12\end{program}\item \clsref{RandomCommand}{../ns-2/misc.cc} defines the command \code{ns-random}. With no argument, \code{ns-random} returns an integer, uniformly distributed in the interval $[0, 2^{31}-1]$. When specified an argument, it takes that argument as the seed. If this seed value is 0, the command uses a heuristic seed value; otherwise, it sets the seed for the random number generator to the specified value.\begin{program} % ns-random \; return a random number; 2078917053 % ns-random 0 \;set the seed heuristically; 858190129 % ns-random 23786 \;set seed to specified value; 23786\end{program}\end{itemize}\emph{Note that, it is generally not advisable to construct top-level commands that are available to the user.}We now describe how to define a new commandusing the example \code{class say_hello}.The example defines the command \code{hi},to print the string ``hello world'',followed by any command line arguments specified by the user.For example,\begin{program} % hi this is ns [ns-version] hello world, this is ns 2.0a12\end{program}\begin{enumerate}\item The command must be defined within a class derived from the \clsref{TclCommand}{../Tcl/Tcl.h}. The class definition is: \begin{program} class say_hello : public TclCommand \{ public: say_hello(); int command(int argc, const char*const* argv); \}; \end{program}\item The constructor for the class must invoke the \fcnref{TclCommand constructor}{../Tcl/Tcl.cc}{TclCommand::TclCommand} with the command as argument; \ie, \begin{program} say_hello() : TclCommand("hi") \{\} \end{program} The \code{TclCommand} constructor sets up "hi" as a global procedure that invokes \fcnref{\fcn[]{TclCommand::dispatch\_cmd}}{../ns-2/Tcl.cc}{TclCommand::dispatch\_cmd}.\item The method \fcn[]{command} must perform the desired action. The method is passed two arguments. The first argument, \code{argc}, contains the number of actual arguments passed by the user. The actual arguments passed by the user are passed as an argument vector (\code{argv}) and contains the following: --- \code{argv[0]} contains the name of the command (\code{hi}). --- \code{argv[1\ldots(argc - 1)]} contains additional arguments specified on the command line by the user. \fcn[]{command} is invoked by \fcn[]{dispatch\_cmd}.\begin{program} #include <streams.h> \* because we are using stream I/O */ int say_hello::command(int argc, const char*const* argv) \{ cout << "hello world:"; for (int i = 1; i < argc; i++) cout << ' ' << argv[i]; cout << '\bs n'; return TCL_OK; \}\end{program}\item Finally, we require an instance of this class. \code{TclCommand} instances are created in the routine \fcnref{\fcn{init\_misc}}{../ns-2/misc.cc}{::init\_misc}. \begin{program} new say_hello; \end{program}\end{enumerate}Note that there used to be more functions such as \code{ns-at}\ and\code{ns-now}\ that were accessible in this manner.Most of these functions have been subsumed into existing classes.In particular, \code{ns-at}\ and \code{ns-now}\ are accessiblethrough the\fcnref{scheduler TclObject}{../ns-2/scheduler.cc}{Scheduler::command}.These functions are defined in \nsf{tcl/lib/ns-lib.tcl}.\begin{program} % set ns [new Simulator] \; get new instance of simulator; _o1 % $ns now \; query simulator for current time; 0 % $ns at \ldots \; specify at operations for simulator; \ldots\end{program} \section{Class EmbeddedTcl}\label{sec:EmbeddedTcl}\ns\ permits the development of functionality in either compiled code,or through interpreter code, that is evaluated at initialization.For example, the scripts \Tclf{tcl-object.tcl} or the scripts in\nsf{tcl/lib}.Such loading and evaluation of scripts is done through objects in the\clsref{EmbeddedTcl}{../Tcl/Tcl.h}.The easiest way to extend \ns\ is to add OTcl codeto either \Tclf{tcl-object.tcl} or through scriptsin the \nsf{tcl/lib} directory.Note that, in the latter case, \ns\ sources\nsf{tcl/lib/ns-lib.tcl} automatically, and hencethe programmer must add a couple of lines to this fileso that their script will also get automatically sourced by \ns\at startup.As an example,the file \nsf{tcl/mcast/srm.tcl} defines some of the instance proceduresto run SRM.In \nsf{tcl/lib/ns-lib.tcl}, we have the lines:\begin{program} source tcl/mcast/srm.tcl\end{program}to automatically get srm.tcl sourced by \ns\ at startup.Three points to note with EmbeddedTcl code are thatfirstly, if the code has an error that is caught during the eval,then \ns\ will not run.Secondly, the user can explicitly override any of the code in the scripts.In particular, they can re-source the entire script after making their ownchanges. Finally, after adding the scripts to \nsf{tcl/lib/ns-lib.tcl}, andevery time thereafter that they change their script, the usermust recompile \ns\ for their changes to take effect.Of course, in most cases\footnote{%The few places where this might not workare when certain variables might have to be defined or undefined,or otherwise the script contains codeother than procedure and variable definitions and executes actions directly that might not be reversible.},the user can source their scriptto override the embedded code.The rest of this subsection illustratehow to integrate individual scripts directly into \ns.The first step is convert the script into an EmbeddedTcl object.The lines below expand ns-lib.tcl and create the EmbeddedTcl objectinstance called \code{et_ns_lib}:\begin{program} tclsh bin/tcl-expand.tcl tcl/lib/ns-lib.tcl | \bs ../Tcl/tcl2c++ et_ns_lib > gen/ns_tcl.cc\end{program}The script, \xref{\nsf{bin/tcl-expand.tcl}}{../ns-2/tcl-expand.tcl}expands \code{ns-lib.tcl} by replacing all \code{source} lineswith the corresponding source files.The program, \xref{\Tclf{tcl2cc.c}}{../Tcl/tcl2c++.c.html},converts the OTcl code into an equivalent EmbeddedTcl object, \code{et_ns_lib}.During initialization, invoking the method \code{EmbeddedTcl::load}explicitly evaluates the array.\begin{list}{---}{}\item \xref{\Tclf{tcl-object.tcl}}{../Tcl/tcl-object.tcl} is evaluated by the method \fcnref{\fcn{Tcl::init}}{../Tcl/Tcl.cc}{Tcl::init}; \fcnref{\fcn[]{Tcl\_AppInit}}{../ns-2/tclAppInit.cc}{::Tcl\_AppInit} invokes \fcn[]{Tcl::Init}. The exact command syntax for the load is: \begin{program} et_tclobject.load(); \end{program}\item Similarly, \xref{\nsf{tcl/lib/ns-lib.tcl}}{../ns-2/tcl/lib/ns-lib.tcl} is evaluated directly by \code{Tcl_AppInit} in \nsf{ns\_tclsh.cc}. \begin{program} et_ns_lib.load(); \end{program}\end{list}\section{Class InstVar}\label{sec:InstVar}This section describes the internals of the \clsref{InstVar}{../Tcl/Tcl.cc}.This class defines the methods and mechanisms to binda C++ member variable in the compiled shadow objectto a specified OTcl instance variable in the equivalent interpreted object.The binding is set up such that the value of the variable can beset or accessed either from within the interpreter, or fromwithin the compiled code at all times.There are five instance variable classes:\clsref{InstVarReal}{../Tcl/Tcl.cc},\clsref{InstVarTime}{../Tcl/Tcl.cc},\clsref{InstVarBandwidth}{../Tcl/Tcl.cc},\clsref{InstVarInt}{../Tcl/Tcl.cc},and \clsref{InstVarBool}{../Tcl/Tcl.cc},corresponding to bindings for real, time, bandwidth, integer, andboolean valued variables respectively.We now describe the mechanism by which instance variables are set up.We use the \clsref{InstVarReal}{../Tcl/Tcl.cc}to illustrate the concept.However, this mechanism is applicable to all five types of instance variables.When setting up an interpreted variable to access a member variable,the member functions of the class InstVar assume that they are executingin the appropriate method execution context;therefore, they do not query the interpreter to determine the context inwhich this variable must exist.In order to guarantee the correct method execution context,a variable must only be bound if its class is already established withinthe interpreter, andthe interpreter is currently operating on an object in that class.Note that the former requires that when a method in a given class isgoing to make its variables accessible via the interpreter,there must be an associated \href{class TclClass}{Section}{sec:TclClass}defined that identifies the appropriate class hierarchy to the interpreter.The appropriate method execution context can therefore be created in oneof two ways.An implicit solution occurs whenever a new TclObject is created withinthe interpreter.This sets up the method execution context within the interpreter.When the compiled shadow object of the interpreted TclObject is created,the constructor for that compiled object can bind its member variablesof that objectto interpreted instance variables in the context of the newly createdinterpreted object.An explicit solution is to define a \code{bind-variables} operationwithin a \code{command} function, that can then be invoked via the\code{cmd} method.The correct method execution context is established in order to executethe \code{cmd} method.Likewise, the compiled code is now operating on the appropriateshadow object, and can therefore safely bind the required member variables.An instance variable is created by specifying the name of theinterpreted variable, and the address of the member variable in thecompiled object.The\fcnref{constructor}{../Tcl/Tcl.cc}{InstVar::InstVar}for the base class InstVar creates an instance of the variable in the interpreter,and then sets up a\fcnref{trap routine}{../Tcl/Tcl.cc}{InstVar::catch_var}to catch all accesses to the variable through the interpreter.Whenever the variable is read through the interpreter, the\fcnref{trap routine}{../Tcl/Tcl.cc}{InstVar::catch_read}is invoked just prior to the occurrence of the read.The routine invokes the appropriate\fcnref{\code{get} function}{../Tcl/Tcl.cc}{InstVarReal::get}that returns the current value of the variable.This value is then used to set the value of the interpreted variablethat is then read by the interpreter.Likewise,whenever the variable is set through the interpreter, the\fcnref{trap routine}{../Tcl/Tcl.cc}{InstVar::catch_write}is invoked just after to the write is completed.The routine gets the current value set by the interpreter, and invokes the appropriate\fcnref{\code{set} function}{../Tcl/Tcl.cc}{InstVarReal::set}that sets the value of the compiled member to the current value setwithin the interpreter.\endinput### Local Variables:### mode: latex### comment-column: 60### backup-by-copying-when-linked: t### file-precious-flag: nil### End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -