The NS simulator is more like an extended TCL language interpreter:
These new commands can be:
#include <stdio.h> #include <string.h> #include "agent.h" // New class is a subclass of Agent // This example will work as subclass // of any C++ class // *********************** // Class header // *********************** class MyAgent : public Agent { public: MyAgent(); // Constructor - binds variables protected: int command(int argc, const char*const* argv); private: int my_var1; // Variable 1 double my_var2; // Variable 2 void MyPrivFunc(void); void showvars(void); }; // *********************** // Class Body // *********************** /* --------------------------------------------------- Constructor: bind variables in C++ class to strings --------------------------------------------------- */ MyAgent::MyAgent() : Agent(PT_UDP) { bind("my_var1_otcl", &my_var1); bind("my_var2_otcl", &my_var2); } /* ------------------------------------------------------------ command: MAIN entry point from TCL call. When TCL executes a command: MyAgent-type-Object x y z Then, this "command" method is invoked with "x" "y" "z" as argv[] parameters to this "command" method !!! ------------------------------------------------------------ */ int MyAgent::command(int argc, const char*const* argv) { /* ----------------------------------------------------------- In this example, we tries to detect 2 possible commands for argv[1]: ----------------------------------------------------------- */ if (strcmp(argv[1], "call-my-priv-func") == 0) { MyPrivFunc(); // invoke the corresponding implementation return(TCL_OK); } else if (strcmp(argv[1], "showvars") == 0) { showvars(); // invoke the corresponding implementation return(TCL_OK); } /* ----------------------------------------------------------- If we arrived here, the command issued was not one of those implemented by MyAgent. But since MyAgent is an Agent, it inherits ALL agent commands. So let Agent handle it... ----------------------------------------------------------- */ return(Agent::command(argc, argv)); } /* ----------------------------------------------------------- MyPrivFunc(): shows how to invoke TCL commands within C++ ----------------------------------------------------------- */ void MyAgent::MyPrivFunc(void) { Tcl& tcl = Tcl::instance(); tcl.eval("puts \"Message From MyPrivFunc\""); tcl.evalf("puts \" my_var1 = %d\"", my_var1); tcl.evalf("puts \" my_var2 = %f\"", my_var2); } /* ----------------------------------------------------------- showvars(): shows an ordinary C++ function ----------------------------------------------------------- */ void MyAgent::showvars(void) { printf("** my_var1 = %d\n", my_var1); printf("** my_var2 = %lf\n", my_var2); } |
set myagent [new Agent/MyAgentOtcl] |
To define (create) a new MyAgent object in TCL (NS):
NOTE: why "new Agent/MyAgentOtcl"? It will be revealed in the binding class soon |
$myagent set my_var1_otcl 2 $myagent set my_var2_otcl 3.14 |
$myagent.my_var1_otcl := 2
$myagent.my_var2_otcl := 3.14 |
$myagent call-my-priv-func $myagent showvars |
Invokes $myagent.call-my-priv-func
Invokes $myagent.showvars |
/* --------------------------------------------- The TCL Binding class for "MyClass" --------------------------------------------- */ static class MyAgentClass : public TclClass { public: /* ----------------------------------------------------------- Constructor - defines the string "Agent/MyAgentOtcl" as a TCL class ----------------------------------------------------------- */ MyAgentClass() : TclClass("Agent/MyAgentOtcl") {} /* ----------------------------------------------------------- create(): method invoked when [new Agent/MyAgentOtcl] is invoked inside a TCL (NS) script ----------------------------------------------------------- */ TclObject* create(int, const char*const*) { return(new MyAgent()); } } class_my_agent; // This defines a STATIC variable of MyAgentClass // type which FORCES C++ to invoke the CONSTRUCTOR |
You may have to edit the script when the version of NS change or the source directory is different
It will create 2 subdirectories and 1 symbolic link:
Initially, it contains copies of a number of often modified header files and TCL scripts. These have been copied for your convenience. If you need to modify other files in the NS source, you need to following these instructions: click here
This directory also contains the new version of the simulator (ns) when you add classes to NS
If you need to modify a NS source file other than those already linked into the NEWDIR/prog, do this:
Find the file in its proper directory - it will be a symbolic link to the NS source directory location.
Let's call this file FOUND-File
cd NEWDIR/prog
cp FOUND-File . (you need to make a copy before you modify it)
(do this inside directory of FOUND-File)
ln -s NEWDIR/prog/FOUND-File .
(now FOUND-File points to the copy in NEWDIR/prog)
NEWDIR/prog/ex-linkage.cc
1. Edit NEWDIR/ns/Makfile
2. Look for the line "OBJ_CC ="
3. Add the line:
../../prog/ex-linkage.o \
NEWDIR/ns/Makefile (which points to NEWDIR/prog/Makefile)
../../prog/ex-linkage.o \as part of the object files
NEWDIR/nsand type "make" - it should compile and make a new "ns" in NEWDIR/ns
cd NEWDIR/prog /home/cheung/thesis/ns/ns/bin/ns ex-linkage.tcl invalid command name "Agent/MyAgentOtcl" ...
cd NEWDIR/prog ../ns/ns ex-linkage.tcl warning: no class variable Agent/MyAgentOtcl::my_var1_otcl see tcl-object.tcl in tclcl for info about this warning. warning: no class variable Agent/MyAgentOtcl::my_var2_otcl Message From MyPrivFunc my_var1 = 2 my_var2 = 3.140000 ** my_var1 = 2 ** my_var2 = 3.140000
This warning messages are caused by the fact that the instance variables have not been initialized.
The warning also gave you a hint on how to fix it: edit ns-default.tcl to initialize the instance variables in order to get rid of the warning message.
Edit:
NEWDIR/ns2/ns-2.26/tcl/lib/ns-default.tcl
(points to prog/ns-default.tcl)
and add the lines:
Agent/MyAgentOtcl set my_var1_otcl 0
Agent/MyAgentOtcl set my_var2_otcl 0
at the end of this file
cd NEWDIR/ns touch ../../prog/ex-linkage.cc make
This should make a new NS that includes the initialization commands for Agent/MyAgentOtcl
cd NEWDIR/prog ../ns/ns ex-linkage.tcl Message From MyPrivFunc my_var1 = 2 my_var2 = 3.140000 ** my_var1 = 2 ** my_var2 = 3.140000