--- a/bindings/python/callbacks_list.py Wed Nov 26 11:45:53 2008 +0000
+++ b/bindings/python/callbacks_list.py Wed Nov 26 12:11:11 2008 +0000
@@ -5,6 +5,7 @@
['void', 'ns3::Ptr<ns3::Socket>', 'unsigned int', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
['void', 'ns3::Ptr<ns3::Socket>', 'ns3::Address const&', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
['bool', 'ns3::Ptr<ns3::Socket>', 'ns3::Address const&', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
+ ['bool', 'std::string', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty', 'ns3::empty'],
['bool', 'ns3::Ptr<ns3::NetDevice>', 'ns3::Ptr<ns3::Packet const>', 'unsigned short', 'ns3::Address const&', 'ns3::Address const&', 'ns3::NetDevice::PacketType'],
['bool', 'ns3::Ptr<ns3::NetDevice>', 'ns3::Ptr<ns3::Packet const>', 'unsigned short', 'ns3::Address const&', 'ns3::empty', 'ns3::empty'],
['void', 'ns3::Ptr<ns3::NetDevice>', 'ns3::Ptr<ns3::Packet const>', 'unsigned short', 'ns3::Address const&', 'ns3::Address const&', 'ns3::NetDevice::PacketType'],
--- a/bindings/python/ns3_module_core.py Wed Nov 26 11:45:53 2008 +0000
+++ b/bindings/python/ns3_module_core.py Wed Nov 26 12:11:11 2008 +0000
@@ -12,7 +12,7 @@
## callback.h: ns3::CallbackImplBase [class]
module.add_class('CallbackImplBase', allow_subclassing=True, memory_policy=cppclass.ReferenceCountingMethodsPolicy(incref_method='Ref', decref_method='Unref', peekref_method='GetReferenceCount'))
## command-line.h: ns3::CommandLine [class]
- module.add_class('CommandLine')
+ module.add_class('CommandLine', allow_subclassing=True)
## system-mutex.h: ns3::CriticalSection [class]
module.add_class('CriticalSection')
## global-value.h: ns3::GlobalValue [class]
@@ -350,6 +350,10 @@
cls.add_constructor([param('ns3::CommandLine const &', 'arg0')])
## command-line.h: ns3::CommandLine::CommandLine() [constructor]
cls.add_constructor([])
+ ## command-line.h: void ns3::CommandLine::AddValue(std::string const & name, std::string const & help, ns3::Callback<bool, std::string, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty> callback) [member function]
+ cls.add_method('AddValue',
+ 'void',
+ [param('std::string const &', 'name'), param('std::string const &', 'help'), param('ns3::Callback< bool, std::string, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'callback')])
return
def register_Ns3CriticalSection_methods(root_module, cls):
--- a/bindings/python/ns3module_helpers.cc Wed Nov 26 11:45:53 2008 +0000
+++ b/bindings/python/ns3module_helpers.cc Wed Nov 26 12:11:11 2008 +0000
@@ -1,3 +1,4 @@
+#include "ns3/ref-count-base.h"
#include "ns3module.h"
@@ -220,3 +221,61 @@
return (PyObject *) py_tid;
}
+
+
+class CommandLinePythonValueSetter : public ns3::RefCountBase
+{
+ PyObject *m_namespace;
+ std::string m_variable;
+public:
+ CommandLinePythonValueSetter (PyObject *ns, std::string const &variable) {
+ Py_INCREF(ns);
+ m_namespace = ns;
+ m_variable = variable;
+ }
+ bool Parse (std::string value) {
+ PyObject *pyvalue = PyString_FromStringAndSize (value.data(), value.size());
+ PyObject_SetAttrString (m_namespace, m_variable.c_str(), pyvalue);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ return false;
+ }
+ return true;
+ }
+ virtual ~CommandLinePythonValueSetter () {
+ Py_DECREF (m_namespace);
+ m_namespace = NULL;
+ }
+
+};
+
+PyObject *
+_wrap_CommandLine_AddValue(PyNs3CommandLine *self, PyObject *args, PyObject *kwargs,
+ PyObject **return_exception)
+{
+ const char *name, *help, *variable = NULL;
+ PyObject *py_namespace = NULL;
+ const char *keywords[] = {"name", "help", "variable", "namespace", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "ss|sO", (char **) keywords, &name, &help, &variable, &py_namespace)) {
+ PyObject *exc_type, *traceback;
+ PyErr_Fetch(&exc_type, return_exception, &traceback);
+ Py_XDECREF(exc_type);
+ Py_XDECREF(traceback);
+ return NULL;
+ }
+
+ if (variable == NULL) {
+ variable = name;
+ }
+ if (py_namespace == NULL) {
+ py_namespace = (PyObject *) self;
+ }
+
+ ns3::Ptr<CommandLinePythonValueSetter> setter = ns3::Create<CommandLinePythonValueSetter> (py_namespace, variable);
+ self->obj->AddValue (name, help, ns3::MakeCallback (&CommandLinePythonValueSetter::Parse, setter));
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
--- a/bindings/python/ns3modulegen_core_customizations.py Wed Nov 26 11:45:53 2008 +0000
+++ b/bindings/python/ns3modulegen_core_customizations.py Wed Nov 26 12:11:11 2008 +0000
@@ -292,6 +292,8 @@
CommandLine = module['ns3::CommandLine']
CommandLine.add_method('Parse', None, [ArgvParam(None, 'argv')],
is_static=False)
+ CommandLine.add_custom_method_wrapper("AddValue", "_wrap_CommandLine_AddValue",
+ flags=["METH_VARARGS", "METH_KEYWORDS"])
def Object_customizations(module):
@@ -523,5 +525,5 @@
TypeId = module['ns3::TypeId']
TypeId.add_custom_method_wrapper("LookupByNameFailSafe", "_wrap_TypeId_LookupByNameFailSafe",
flags=["METH_VARARGS", "METH_KEYWORDS", "METH_STATIC"])
-
+
--- a/bindings/python/ns3modulescan.py Wed Nov 26 11:45:53 2008 +0000
+++ b/bindings/python/ns3modulescan.py Wed Nov 26 12:11:11 2008 +0000
@@ -56,6 +56,11 @@
'automatic_type_narrowing': 'true',
'allow_subclassing': 'false',
},
+
+ '::ns3::CommandLine': {
+ 'allow_subclassing': 'true', # needed so that AddValue is able to set attributes on the object
+ },
+
'ns3::RandomVariable::RandomVariable(ns3::RandomVariableBase const & variable) [constructor]': {
'ignore': None,
},
--- a/bindings/python/wscript Wed Nov 26 11:45:53 2008 +0000
+++ b/bindings/python/wscript Wed Nov 26 12:11:11 2008 +0000
@@ -309,6 +309,7 @@
t1 > t2;
}
+
}
"""
outfile.close()
--- a/src/core/command-line.cc Wed Nov 26 11:45:53 2008 +0000
+++ b/src/core/command-line.cc Wed Nov 26 12:11:11 2008 +0000
@@ -253,6 +253,27 @@
}
}
+bool
+CommandLine::CallbackItem::Parse (std::string value)
+{
+ NS_LOG_DEBUG ("CommandLine::CallbackItem::Parse \"" << value << "\"");
+ return m_callback (value);
+}
+
+void
+CommandLine::AddValue (const std::string &name,
+ const std::string &help,
+ Callback<bool, std::string> callback)
+{
+ NS_LOG_FUNCTION (this << name << help << "callback");
+ CallbackItem *item = new CallbackItem ();
+ item->m_name = name;
+ item->m_help = help;
+ item->m_callback = callback;
+ m_items.push_back (item);
+}
+
+
} // namespace ns3
#ifdef RUN_SELF_TESTS
--- a/src/core/command-line.h Wed Nov 26 11:45:53 2008 +0000
+++ b/src/core/command-line.h Wed Nov 26 12:11:11 2008 +0000
@@ -24,6 +24,8 @@
#include <sstream>
#include <list>
+#include "ns3/callback.h"
+
namespace ns3 {
/**
@@ -56,6 +58,17 @@
const std::string &help,
T &value);
+
+ /**
+ * \param name the name of the user-supplied argument
+ * \param help some help text used by --PrintHelp
+ * \param callback a callback function that will be invoked to parse
+ * and collect the value. This normally used by language bindings.
+ */
+ void AddValue (const std::string &name,
+ const std::string &help,
+ Callback<bool, std::string> callback);
+
/**
* \param argc the 'argc' variable: number of arguments (including the
* main program name as first element).
@@ -82,6 +95,13 @@
virtual bool Parse (std::string value);
T *m_valuePtr;
};
+ class CallbackItem : public Item
+ {
+ public:
+ virtual bool Parse (std::string value);
+ Callback<bool, std::string> m_callback;
+ };
+
void HandleArgument (std::string name, std::string value) const;
void PrintHelp (void) const;
void PrintGlobals (void) const;
--- a/utils/python-unit-tests.py Wed Nov 26 11:45:53 2008 +0000
+++ b/utils/python-unit-tests.py Wed Nov 26 12:11:11 2008 +0000
@@ -123,5 +123,26 @@
self.assertRaises(KeyError, ns3.TypeId.LookupByNameFailSafe, "__InvalidTypeName__")
+ def testCommandLine(self):
+ cmd = ns3.CommandLine()
+ cmd.AddValue("Test1", "this is a test option")
+ cmd.AddValue("Test2", "this is a test option")
+ cmd.AddValue("Test3", "this is a test option", variable="test_xxx")
+ cmd.Test1 = None
+ cmd.Test2 = None
+ cmd.test_xxx = None
+ class Foo:
+ pass
+ foo = Foo()
+ foo.test_foo = None
+ cmd.AddValue("Test4", "this is a test option", variable="test_foo", namespace=foo)
+
+ cmd.Parse(["python", "--Test1=value1", "--Test2=value2", "--Test3=123", "--Test4=xpto"])
+
+ self.assertEqual(cmd.Test1, "value1")
+ self.assertEqual(cmd.Test2, "value2")
+ self.assertEqual(cmd.test_xxx, "123")
+ self.assertEqual(foo.test_foo, "xpto")
+
if __name__ == '__main__':
unittest.main()