We will consider onePhasePullFilter object (under diffusion3/filters/misc/log.*) as an example. As a first step you need to create a split object out of the application class object, presumably defined as a pure c++ object. A split object is one that is created by the user in the interpretor (in OTcl space) and which is also has a shadow object in the compiled hierarchy (in c++ space). In ns, a split object is derived from class TclClass as shown below:
#ifdef NS_DIFFUSION static class LogFilterClass : public TclClass { public: LogFilterClass() : TclClass("Application/DiffApp/LogFilter") {} TclObject * create(int argc, const char*const* argv) { return(new LogFilter()); } } class_log_filter; #endif //DIFFUSION
Note that all filter objects specifically have a handle to the DiffAppAgent (the diffusion routing object) passed in the constructor call. Filter objects get created from function create-diffusionApp-agent diffFilters defined in ns-diffusion.tcl. Users need not specifically call the OTcl function create-diffusionApp-agent as it is called during node creation based on the node-configuration parameters. See how filters are defined in node-config under commands at a glance section. However application objects which are not filter objects (like ping_sender, push_receiver etc) are created by users directly from user scripts. And in that case the handle to DiffAppAgent is passed using $ns attach-diffapp $node $app where the application $app is attached to the node object $node.
So for the reasons explained above the constructors are different in non NS_DIFFUSION context as shown below.
#ifdef NS_DIFFUSION LogFilter::LogFilter() #else LogFilter::LogFilter(int argc, char **argv) #endif // NS_DIFFUSION { // Create Diffusion Routing class #ifndef NS_DIFFUSION parseCommandLine(argc, argv); dr_ = NR::createNR(diffusion_port_); #endif // !NS_DIFFUSION filter_callback_ = new LogFilterReceive(this); #ifndef NS_DIFFUSION // Set up the filter filter_handle_ = setupFilter(); ... ... #endif // !NS_DIFFUSION }
Next you need to add the c++ function command(..) that allows execution of tcl commands through the compiled shadow object. For example the otcl command start is used to start a filter application as follows $app start. While commands publish and subscribe are used to start sender and receiver applications respectively. The command function is added, again with the NS_DIFFUSION scope using ifdef statements, as follows:
#ifdef NS_DIFFUSION int LogFilter::command(int argc, const char*const* argv) { if (argc == 2) { if (strcmp(argv[1], "start") == 0) { run(); return TCL_OK; } } return DiffApp::command(argc, argv); } #endif // NS_DIFFUSION
Note how the parent class command function is invoked incase the command string is not found. Look into lib/diffapp.* to see all otcl commands supported for the DiffApp class.
Once these changes made to your c++ code, you would also need to write a tcl script (see the section on test-suite for example tcl scripts) that uses your diffusion application using the right tcl APIs.
Tom Henderson 2011-11-05