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