diff --git a/src/config-store/bindings/modulegen_customizations.py b/src/config-store/bindings/modulegen_customizations.py new file mode 100644 index 000000000..3a3632f9a --- /dev/null +++ b/src/config-store/bindings/modulegen_customizations.py @@ -0,0 +1,10 @@ +import os + +def post_register_types(root_module): + enabled_features = os.environ['NS3_ENABLED_FEATURES'].split(',') + # if GtkConfigStore support is disabled, disable the class wrapper + if 'GtkConfigStore' not in enabled_features: + try: + root_module.classes.remove(root_module['ns3::GtkConfigStore']) + except KeyError: + pass diff --git a/src/core/bindings/modulegen_customizations.py b/src/core/bindings/modulegen_customizations.py index 0f090f0fb..7ebff3855 100644 --- a/src/core/bindings/modulegen_customizations.py +++ b/src/core/bindings/modulegen_customizations.py @@ -1,4 +1,6 @@ import re +import os +import sys from pybindgen.typehandlers import base as typehandlers from pybindgen import ReturnValue, Parameter @@ -10,77 +12,76 @@ import warnings from pybindgen.typehandlers.base import CodeGenerationError -import sys -class SmartPointerTransformation(typehandlers.TypeTransformation): - """ - This class provides a "type transformation" that tends to support - NS-3 smart pointers. Parameters such as "Ptr foo" are - transformed into something like Parameter.new("Foo*", "foo", - transfer_ownership=False). Return values such as Ptr are - transformed into ReturnValue.new("Foo*", - caller_owns_return=False). Since the underlying objects have - reference counting, PyBindGen does the right thing. - """ - def __init__(self): - super(SmartPointerTransformation, self).__init__() - self.rx = re.compile(r'(ns3::|::ns3::|)Ptr<([^>]+)>\s*$') +# class SmartPointerTransformation(typehandlers.TypeTransformation): +# """ +# This class provides a "type transformation" that tends to support +# NS-3 smart pointers. Parameters such as "Ptr foo" are +# transformed into something like Parameter.new("Foo*", "foo", +# transfer_ownership=False). Return values such as Ptr are +# transformed into ReturnValue.new("Foo*", +# caller_owns_return=False). Since the underlying objects have +# reference counting, PyBindGen does the right thing. +# """ +# def __init__(self): +# super(SmartPointerTransformation, self).__init__() +# self.rx = re.compile(r'(ns3::|::ns3::|)Ptr<([^>]+)>\s*$') - def _get_untransformed_type_traits(self, name): - m = self.rx.match(name) - is_const = False - if m is None: - return None, False - else: - name1 = m.group(2).strip() - if name1.startswith('const '): - name1 = name1[len('const '):] - is_const = True - if name1.endswith(' const'): - name1 = name1[:-len(' const')] - is_const = True - new_name = name1+' *' +# def _get_untransformed_type_traits(self, name): +# m = self.rx.match(name) +# is_const = False +# if m is None: +# return None, False +# else: +# name1 = m.group(2).strip() +# if name1.startswith('const '): +# name1 = name1[len('const '):] +# is_const = True +# if name1.endswith(' const'): +# name1 = name1[:-len(' const')] +# is_const = True +# new_name = name1+' *' - if new_name.startswith('::'): - new_name = new_name[2:] - return new_name, is_const +# if new_name.startswith('::'): +# new_name = new_name[2:] +# return new_name, is_const - def get_untransformed_name(self, name): - new_name, dummy_is_const = self._get_untransformed_type_traits(name) - return new_name +# def get_untransformed_name(self, name): +# new_name, dummy_is_const = self._get_untransformed_type_traits(name) +# return new_name - def create_type_handler(self, type_handler, *args, **kwargs): - if issubclass(type_handler, Parameter): - kwargs['transfer_ownership'] = False - elif issubclass(type_handler, ReturnValue): - kwargs['caller_owns_return'] = False - else: - raise AssertionError +# def create_type_handler(self, type_handler, *args, **kwargs): +# if issubclass(type_handler, Parameter): +# kwargs['transfer_ownership'] = False +# elif issubclass(type_handler, ReturnValue): +# kwargs['caller_owns_return'] = False +# else: +# raise AssertionError - ## fix the ctype, add ns3:: namespace - orig_ctype, is_const = self._get_untransformed_type_traits(args[0]) - if is_const: - correct_ctype = 'ns3::Ptr< %s const >' % orig_ctype[:-2] - else: - correct_ctype = 'ns3::Ptr< %s >' % orig_ctype[:-2] - args = tuple([correct_ctype] + list(args[1:])) +# ## fix the ctype, add ns3:: namespace +# orig_ctype, is_const = self._get_untransformed_type_traits(args[0]) +# if is_const: +# correct_ctype = 'ns3::Ptr< %s const >' % orig_ctype[:-2] +# else: +# correct_ctype = 'ns3::Ptr< %s >' % orig_ctype[:-2] +# args = tuple([correct_ctype] + list(args[1:])) - handler = type_handler(*args, **kwargs) - handler.set_tranformation(self, orig_ctype) - return handler +# handler = type_handler(*args, **kwargs) +# handler.set_tranformation(self, orig_ctype) +# return handler - def untransform(self, type_handler, declarations, code_block, expression): - return 'const_cast<%s> (ns3::PeekPointer (%s))' % (type_handler.untransformed_ctype, expression) +# def untransform(self, type_handler, declarations, code_block, expression): +# return 'const_cast<%s> (ns3::PeekPointer (%s))' % (type_handler.untransformed_ctype, expression) - def transform(self, type_handler, declarations, code_block, expression): - assert type_handler.untransformed_ctype[-1] == '*' - return 'ns3::Ptr< %s > (%s)' % (type_handler.untransformed_ctype[:-1], expression) +# def transform(self, type_handler, declarations, code_block, expression): +# assert type_handler.untransformed_ctype[-1] == '*' +# return 'ns3::Ptr< %s > (%s)' % (type_handler.untransformed_ctype[:-1], expression) -## register the type transformation -transf = SmartPointerTransformation() -typehandlers.return_type_matcher.register_transformation(transf) -typehandlers.param_type_matcher.register_transformation(transf) -del transf +# ## register the type transformation +# transf = SmartPointerTransformation() +# typehandlers.return_type_matcher.register_transformation(transf) +# typehandlers.param_type_matcher.register_transformation(transf) +# del transf class ArgvParam(Parameter): @@ -135,158 +136,158 @@ PyObject *item = PyList_GET_ITEM(%(py_name)s, %(idx)s); wrapper.call_params.append(name) -class CallbackImplProxyMethod(typehandlers.ReverseWrapperBase): - """ - Class that generates a proxy virtual method that calls a similarly named python method. - """ +# class CallbackImplProxyMethod(typehandlers.ReverseWrapperBase): +# """ +# Class that generates a proxy virtual method that calls a similarly named python method. +# """ - def __init__(self, return_value, parameters): - super(CallbackImplProxyMethod, self).__init__(return_value, parameters) +# def __init__(self, return_value, parameters): +# super(CallbackImplProxyMethod, self).__init__(return_value, parameters) - def generate_python_call(self): - """code to call the python method""" - build_params = self.build_params.get_parameters(force_tuple_creation=True) - if build_params[0][0] == '"': - build_params[0] = '(char *) ' + build_params[0] - args = self.before_call.declare_variable('PyObject*', 'args') - self.before_call.write_code('%s = Py_BuildValue(%s);' - % (args, ', '.join(build_params))) - self.before_call.add_cleanup_code('Py_DECREF(%s);' % args) - self.before_call.write_code('py_retval = PyObject_CallObject(m_callback, %s);' % args) - self.before_call.write_error_check('py_retval == NULL') - self.before_call.add_cleanup_code('Py_DECREF(py_retval);') +# def generate_python_call(self): +# """code to call the python method""" +# build_params = self.build_params.get_parameters(force_tuple_creation=True) +# if build_params[0][0] == '"': +# build_params[0] = '(char *) ' + build_params[0] +# args = self.before_call.declare_variable('PyObject*', 'args') +# self.before_call.write_code('%s = Py_BuildValue(%s);' +# % (args, ', '.join(build_params))) +# self.before_call.add_cleanup_code('Py_DECREF(%s);' % args) +# self.before_call.write_code('py_retval = PyObject_CallObject(m_callback, %s);' % args) +# self.before_call.write_error_check('py_retval == NULL') +# self.before_call.add_cleanup_code('Py_DECREF(py_retval);') -def generate_callback_classes(out, callbacks): - for callback_impl_num, template_parameters in enumerate(callbacks): - sink = MemoryCodeSink() - cls_name = "ns3::Callback< %s >" % ', '.join(template_parameters) - #print >> sys.stderr, "***** trying to register callback: %r" % cls_name - class_name = "PythonCallbackImpl%i" % callback_impl_num - sink.writeln(''' -class %s : public ns3::CallbackImpl<%s> -{ -public: - PyObject *m_callback; - %s(PyObject *callback) - { - Py_INCREF(callback); - m_callback = callback; - } - virtual ~%s() - { - Py_DECREF(m_callback); - m_callback = NULL; - } +# def generate_callback_classes(out, callbacks): +# for callback_impl_num, template_parameters in enumerate(callbacks): +# sink = MemoryCodeSink() +# cls_name = "ns3::Callback< %s >" % ', '.join(template_parameters) +# #print >> sys.stderr, "***** trying to register callback: %r" % cls_name +# class_name = "PythonCallbackImpl%i" % callback_impl_num +# sink.writeln(''' +# class %s : public ns3::CallbackImpl<%s> +# { +# public: +# PyObject *m_callback; +# %s(PyObject *callback) +# { +# Py_INCREF(callback); +# m_callback = callback; +# } +# virtual ~%s() +# { +# Py_DECREF(m_callback); +# m_callback = NULL; +# } - virtual bool IsEqual(ns3::Ptr other_base) const - { - const %s *other = dynamic_cast (ns3::PeekPointer (other_base)); - if (other != NULL) - return (other->m_callback == m_callback); - else - return false; - } +# virtual bool IsEqual(ns3::Ptr other_base) const +# { +# const %s *other = dynamic_cast (ns3::PeekPointer (other_base)); +# if (other != NULL) +# return (other->m_callback == m_callback); +# else +# return false; +# } -''' % (class_name, ', '.join(template_parameters), class_name, class_name, class_name, class_name)) - sink.indent() - callback_return = template_parameters[0] - return_ctype = ctypeparser.parse_type(callback_return) - if ('const' in return_ctype.remove_modifiers()): - kwargs = {'is_const': True} - else: - kwargs = {} - try: - return_type = ReturnValue.new(str(return_ctype), **kwargs) - except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError), ex: - warnings.warn("***** Unable to register callback; Return value '%s' error (used in %s): %r" - % (callback_return, cls_name, ex), - Warning) - continue +# ''' % (class_name, ', '.join(template_parameters), class_name, class_name, class_name, class_name)) +# sink.indent() +# callback_return = template_parameters[0] +# return_ctype = ctypeparser.parse_type(callback_return) +# if ('const' in return_ctype.remove_modifiers()): +# kwargs = {'is_const': True} +# else: +# kwargs = {} +# try: +# return_type = ReturnValue.new(str(return_ctype), **kwargs) +# except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError), ex: +# warnings.warn("***** Unable to register callback; Return value '%s' error (used in %s): %r" +# % (callback_return, cls_name, ex), +# Warning) +# continue - arguments = [] - ok = True - callback_parameters = [arg for arg in template_parameters[1:] if arg != 'ns3::empty'] - for arg_num, arg_type in enumerate(callback_parameters): - arg_name = 'arg%i' % (arg_num+1) +# arguments = [] +# ok = True +# callback_parameters = [arg for arg in template_parameters[1:] if arg != 'ns3::empty'] +# for arg_num, arg_type in enumerate(callback_parameters): +# arg_name = 'arg%i' % (arg_num+1) - param_ctype = ctypeparser.parse_type(arg_type) - if ('const' in param_ctype.remove_modifiers()): - kwargs = {'is_const': True} - else: - kwargs = {} - try: - arguments.append(Parameter.new(str(param_ctype), arg_name, **kwargs)) - except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError), ex: - warnings.warn("***** Unable to register callback; parameter '%s %s' error (used in %s): %r" - % (arg_type, arg_name, cls_name, ex), - Warning) - ok = False - if not ok: - continue +# param_ctype = ctypeparser.parse_type(arg_type) +# if ('const' in param_ctype.remove_modifiers()): +# kwargs = {'is_const': True} +# else: +# kwargs = {} +# try: +# arguments.append(Parameter.new(str(param_ctype), arg_name, **kwargs)) +# except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError), ex: +# warnings.warn("***** Unable to register callback; parameter '%s %s' error (used in %s): %r" +# % (arg_type, arg_name, cls_name, ex), +# Warning) +# ok = False +# if not ok: +# continue - wrapper = CallbackImplProxyMethod(return_type, arguments) - wrapper.generate(sink, 'operator()', decl_modifiers=[]) +# wrapper = CallbackImplProxyMethod(return_type, arguments) +# wrapper.generate(sink, 'operator()', decl_modifiers=[]) - sink.unindent() - sink.writeln('};\n') - sink.flush_to(out) +# sink.unindent() +# sink.writeln('};\n') +# sink.flush_to(out) - class PythonCallbackParameter(Parameter): - "Class handlers" - CTYPES = [cls_name] - #print >> sys.stderr, "***** registering callback handler: %r" % ctypeparser.normalize_type_string(cls_name) - DIRECTIONS = [Parameter.DIRECTION_IN] - PYTHON_CALLBACK_IMPL_NAME = class_name - TEMPLATE_ARGS = template_parameters +# class PythonCallbackParameter(Parameter): +# "Class handlers" +# CTYPES = [cls_name] +# #print >> sys.stderr, "***** registering callback handler: %r" % ctypeparser.normalize_type_string(cls_name) +# DIRECTIONS = [Parameter.DIRECTION_IN] +# PYTHON_CALLBACK_IMPL_NAME = class_name +# TEMPLATE_ARGS = template_parameters - def convert_python_to_c(self, wrapper): - "parses python args to get C++ value" - assert isinstance(wrapper, typehandlers.ForwardWrapperBase) +# def convert_python_to_c(self, wrapper): +# "parses python args to get C++ value" +# assert isinstance(wrapper, typehandlers.ForwardWrapperBase) - if self.default_value is None: - py_callback = wrapper.declarations.declare_variable('PyObject*', self.name) - wrapper.parse_params.add_parameter('O', ['&'+py_callback], self.name) - wrapper.before_call.write_error_check( - '!PyCallable_Check(%s)' % py_callback, - 'PyErr_SetString(PyExc_TypeError, "parameter \'%s\' must be callbale");' % self.name) - callback_impl = wrapper.declarations.declare_variable( - 'ns3::Ptr<%s>' % self.PYTHON_CALLBACK_IMPL_NAME, - '%s_cb_impl' % self.name) - wrapper.before_call.write_code("%s = ns3::Create<%s> (%s);" - % (callback_impl, self.PYTHON_CALLBACK_IMPL_NAME, py_callback)) - wrapper.call_params.append( - 'ns3::Callback<%s> (%s)' % (', '.join(self.TEMPLATE_ARGS), callback_impl)) - else: - py_callback = wrapper.declarations.declare_variable('PyObject*', self.name, 'NULL') - wrapper.parse_params.add_parameter('O', ['&'+py_callback], self.name, optional=True) - value = wrapper.declarations.declare_variable( - 'ns3::Callback<%s>' % ', '.join(self.TEMPLATE_ARGS), - self.name+'_value', - self.default_value) +# if self.default_value is None: +# py_callback = wrapper.declarations.declare_variable('PyObject*', self.name) +# wrapper.parse_params.add_parameter('O', ['&'+py_callback], self.name) +# wrapper.before_call.write_error_check( +# '!PyCallable_Check(%s)' % py_callback, +# 'PyErr_SetString(PyExc_TypeError, "parameter \'%s\' must be callbale");' % self.name) +# callback_impl = wrapper.declarations.declare_variable( +# 'ns3::Ptr<%s>' % self.PYTHON_CALLBACK_IMPL_NAME, +# '%s_cb_impl' % self.name) +# wrapper.before_call.write_code("%s = ns3::Create<%s> (%s);" +# % (callback_impl, self.PYTHON_CALLBACK_IMPL_NAME, py_callback)) +# wrapper.call_params.append( +# 'ns3::Callback<%s> (%s)' % (', '.join(self.TEMPLATE_ARGS), callback_impl)) +# else: +# py_callback = wrapper.declarations.declare_variable('PyObject*', self.name, 'NULL') +# wrapper.parse_params.add_parameter('O', ['&'+py_callback], self.name, optional=True) +# value = wrapper.declarations.declare_variable( +# 'ns3::Callback<%s>' % ', '.join(self.TEMPLATE_ARGS), +# self.name+'_value', +# self.default_value) - wrapper.before_call.write_code("if (%s) {" % (py_callback,)) - wrapper.before_call.indent() +# wrapper.before_call.write_code("if (%s) {" % (py_callback,)) +# wrapper.before_call.indent() - wrapper.before_call.write_error_check( - '!PyCallable_Check(%s)' % py_callback, - 'PyErr_SetString(PyExc_TypeError, "parameter \'%s\' must be callbale");' % self.name) +# wrapper.before_call.write_error_check( +# '!PyCallable_Check(%s)' % py_callback, +# 'PyErr_SetString(PyExc_TypeError, "parameter \'%s\' must be callbale");' % self.name) - wrapper.before_call.write_code("%s = ns3::Callback<%s> (ns3::Create<%s> (%s));" - % (value, ', '.join(self.TEMPLATE_ARGS), - self.PYTHON_CALLBACK_IMPL_NAME, py_callback)) +# wrapper.before_call.write_code("%s = ns3::Callback<%s> (ns3::Create<%s> (%s));" +# % (value, ', '.join(self.TEMPLATE_ARGS), +# self.PYTHON_CALLBACK_IMPL_NAME, py_callback)) - wrapper.before_call.unindent() - wrapper.before_call.write_code("}") # closes: if (py_callback) { +# wrapper.before_call.unindent() +# wrapper.before_call.write_code("}") # closes: if (py_callback) { - wrapper.call_params.append(value) +# wrapper.call_params.append(value) - def convert_c_to_python(self, wrapper): - raise typehandlers.NotSupportedError("Reverse wrappers for ns3::Callback<...> types " - "(python using callbacks defined in C++) not implemented.") +# def convert_c_to_python(self, wrapper): +# raise typehandlers.NotSupportedError("Reverse wrappers for ns3::Callback<...> types " +# "(python using callbacks defined in C++) not implemented.") # def write_preamble(out): @@ -476,6 +477,18 @@ def post_register_types(root_module): add_std_ofstream(root_module) add_scalar_operators(root_module) + enabled_features = os.environ['NS3_ENABLED_FEATURES'].split(',') + + if 'Threading' not in enabled_features: + for clsname in ['SystemThread', 'SystemMutex', 'SystemCondition', 'CriticalSection', + 'SimpleRefCount< ns3::SystemThread, ns3::empty, ns3::DefaultDeleter >']: + root_module.classes.remove(root_module['ns3::%s' % clsname]) + + if 'RealTime' not in enabled_features: + for clsname in ['WallClockSynchronizer', 'RealtimeSimulatorImpl']: + root_module.classes.remove(root_module['ns3::%s' % clsname]) + root_module.enums.remove(root_module['ns3::RealtimeSimulatorImpl::SynchronizationMode']) + # these are already in the main script, so commented out here # Object_customizations(root_module) diff --git a/src/emu/bindings/modulegen_customizations.py b/src/emu/bindings/modulegen_customizations.py new file mode 100644 index 000000000..cd8b4caf0 --- /dev/null +++ b/src/emu/bindings/modulegen_customizations.py @@ -0,0 +1,10 @@ +import os + +def post_register_types(root_module): + enabled_features = os.environ['NS3_ENABLED_FEATURES'].split(',') + + if 'EmuNetDevice' not in enabled_features: + for clsname in ['EmuNetDevice', 'EmuHelper']: + root_module.classes.remove(root_module['ns3::%s' % clsname]) + root_module.enums.remove(root_module['ns3::EmuNetDevice::EncapsulationMode']) + diff --git a/src/stats/bindings/modulegen_customizations.py b/src/stats/bindings/modulegen_customizations.py new file mode 100644 index 000000000..e2e56ed26 --- /dev/null +++ b/src/stats/bindings/modulegen_customizations.py @@ -0,0 +1,12 @@ +import os + +def post_register_types(root_module): + enabled_features = os.environ['NS3_ENABLED_FEATURES'].split(',') + + # if no sqlite, the class SqliteDataOutput is disabled + if 'SqliteDataOutput' not in enabled_features: + try: + root_module.classes.remove(root_module['ns3::SqliteDataOutput']) + except KeyError: + pass + diff --git a/src/tap-bridge/bindings/modulegen_customizations.py b/src/tap-bridge/bindings/modulegen_customizations.py new file mode 100644 index 000000000..d9d1e6ac4 --- /dev/null +++ b/src/tap-bridge/bindings/modulegen_customizations.py @@ -0,0 +1,9 @@ +import os + +def post_register_types(root_module): + enabled_features = os.environ['NS3_ENABLED_FEATURES'].split(',') + + if 'TapBridge' not in enabled_features: + for clsname in ['TapBridge', 'TapBridgeHelper', 'TapBridgeFdReader']: + root_module.classes.remove(root_module['ns3::%s' % clsname]) + root_module.enums.remove(root_module['ns3::TapBridge::Mode'])