diff --git a/bindings/python/ns3modulegen-modular.py b/bindings/python/ns3modulegen-modular.py index 4b40c1be5..248c431f3 100644 --- a/bindings/python/ns3modulegen-modular.py +++ b/bindings/python/ns3modulegen-modular.py @@ -1,3 +1,4 @@ +from __future__ import print_function import warnings import sys import os @@ -76,11 +77,11 @@ def main(argv): try: from callbacks_list import callback_classes - except ImportError, ex: - print >> sys.stderr, "***************", repr(ex) + except ImportError as ex: + print("***************", repr(ex), file=sys.stderr) callback_classes = [] else: - print >> sys.stderr, ">>>>>>>>>>>>>>>>", repr(callback_classes) + print(">>>>>>>>>>>>>>>>", repr(callback_classes), file=sys.stderr) finally: sys.path.pop(0) diff --git a/bindings/python/ns3modulegen_core_customizations.py b/bindings/python/ns3modulegen_core_customizations.py index c4ff74bea..19c2d5114 100644 --- a/bindings/python/ns3modulegen_core_customizations.py +++ b/bindings/python/ns3modulegen_core_customizations.py @@ -1,3 +1,5 @@ +from __future__ import print_function +import sys import re from pybindgen.typehandlers import base as typehandlers @@ -26,11 +28,13 @@ class SmartPointerTransformation(typehandlers.TypeTransformation): def __init__(self): super(SmartPointerTransformation, self).__init__() self.rx = re.compile(r'(ns3::|::ns3::|)Ptr<([^>]+)>\s*$') + print("{!r}".format(self), file=sys.stderr) def _get_untransformed_type_traits(self, name): m = self.rx.match(name) is_const = False if m is None: + print("{!r} did not match".format(name), file=sys.stderr) return None, False else: name1 = m.group(2).strip() @@ -61,9 +65,9 @@ class SmartPointerTransformation(typehandlers.TypeTransformation): ## 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] + correct_ctype = 'ns3::Ptr< {} const >'.format(orig_ctype[:-2]) else: - correct_ctype = 'ns3::Ptr< %s >' % orig_ctype[:-2] + correct_ctype = 'ns3::Ptr< {} >'.format(orig_ctype[:-2]) args = tuple([correct_ctype] + list(args[1:])) handler = type_handler(*args, **kwargs) @@ -84,58 +88,6 @@ typehandlers.param_type_matcher.register_transformation(transf) del transf -class ArgvParam(Parameter): - """ - Converts a python list-of-strings argument to a pair of 'int argc, - char *argv[]' arguments to pass into C. - - One Python argument becomes two C function arguments -> it's a miracle! - - Note: this parameter type handler is not registered by any name; - must be used explicitly. - """ - - DIRECTIONS = [Parameter.DIRECTION_IN] - CTYPES = [] - - def convert_c_to_python(self, wrapper): - raise NotImplementedError - - def convert_python_to_c(self, wrapper): - py_name = wrapper.declarations.declare_variable('PyObject*', 'py_' + self.name) - argc_var = wrapper.declarations.declare_variable('int', 'argc') - name = wrapper.declarations.declare_variable('char**', self.name) - idx = wrapper.declarations.declare_variable('Py_ssize_t', 'idx') - wrapper.parse_params.add_parameter('O!', ['&PyList_Type', '&'+py_name], self.name) - - #wrapper.before_call.write_error_check('!PyList_Check(%s)' % py_name) # XXX - - wrapper.before_call.write_code("%s = (char **) malloc(sizeof(char*)*PyList_Size(%s));" - % (name, py_name)) - wrapper.before_call.add_cleanup_code('free(%s);' % name) - wrapper.before_call.write_code(''' -for (%(idx)s = 0; %(idx)s < PyList_Size(%(py_name)s); %(idx)s++) -{ -''' % vars()) - wrapper.before_call.sink.indent() - wrapper.before_call.write_code(''' -PyObject *item = PyList_GET_ITEM(%(py_name)s, %(idx)s); -''' % vars()) - #wrapper.before_call.write_error_check('item == NULL') - wrapper.before_call.write_error_check( - '!PyString_Check(item)', - failure_cleanup=('PyErr_SetString(PyExc_TypeError, ' - '"argument %s must be a list of strings");') % self.name) - wrapper.before_call.write_code( - '%s[%s] = PyString_AsString(item);' % (name, idx)) - wrapper.before_call.sink.unindent() - wrapper.before_call.write_code('}') - wrapper.before_call.write_code('%s = PyList_Size(%s);' % (argc_var, py_name)) - - wrapper.call_params.append(argc_var) - wrapper.call_params.append(name) - - class CallbackImplProxyMethod(typehandlers.ReverseWrapperBase): """ Class that generates a proxy virtual method that calls a similarly named python method. @@ -204,7 +156,7 @@ public: kwargs = {} try: return_type = ReturnValue.new(str(return_ctype), **kwargs) - except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError), ex: + except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError) as ex: warnings.warn("***** Unable to register callback; Return value '%s' error (used in %s): %r" % (callback_return, cls_name, ex), Warning) @@ -223,7 +175,7 @@ public: kwargs = {} try: arguments.append(Parameter.new(str(param_ctype), arg_name, **kwargs)) - except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError), ex: + except (typehandlers.TypeLookupError, typehandlers.TypeConfigurationError) as ex: warnings.warn("***** Unable to register callback; parameter '%s %s' error (used in %s): %r" % (arg_type, arg_name, cls_name, ex), Warning) @@ -241,7 +193,7 @@ public: class PythonCallbackParameter(Parameter): "Class handlers" CTYPES = [cls_name] - print >> sys.stderr, "***** registering callback handler: %r" % ctypeparser.normalize_type_string(cls_name) + print("***** registering callback handler: %r" % ctypeparser.normalize_type_string(cls_name), file=sys.stderr) DIRECTIONS = [Parameter.DIRECTION_IN] PYTHON_CALLBACK_IMPL_NAME = class_name TEMPLATE_ARGS = template_parameters diff --git a/bindings/python/wscript b/bindings/python/wscript index f0794fc9f..f61a4cec3 100644 --- a/bindings/python/wscript +++ b/bindings/python/wscript @@ -13,7 +13,7 @@ from waflib.Errors import WafError # after = TaskGen.after ## https://launchpad.net/pybindgen/ -REQUIRED_PYBINDGEN_VERSION = (0, 17, 0, 866) +REQUIRED_PYBINDGEN_VERSION = (0, 17, 0, 868) REQUIRED_PYGCCXML_VERSION = (0, 9, 5) RUN_ME=-3 @@ -165,7 +165,7 @@ def configure(conf): else: out = subprocess.Popen([conf.env['PYTHON'][0], "-c", "import pybindgen.version; " - "print '.'.join([str(x) for x in pybindgen.version.__version__])"], + "print('.'.join([str(x) for x in pybindgen.version.__version__]))"], stdout=subprocess.PIPE).communicate()[0] pybindgen_version_str = out.strip() pybindgen_version = tuple([int(x) for x in pybindgen_version_str.split('.')]) diff --git a/src/core/bindings/core.py b/src/core/bindings/core.py index 53fd4ca75..187cddb73 100644 --- a/src/core/bindings/core.py +++ b/src/core/bindings/core.py @@ -1,10 +1,10 @@ - +from __future__ import absolute_import # "from _core import *" doesn't work here because symbols starting # with underscore would not be imported. But they are needed because # other modules depend on them... -import _core +from . import _core g = globals() -for k,v in _core.__dict__.iteritems(): +for k,v in _core.__dict__.items(): g[k] = v del g, k, v, _core diff --git a/src/core/bindings/module_helpers.cc b/src/core/bindings/module_helpers.cc index e270109f1..bc418c67d 100644 --- a/src/core/bindings/module_helpers.cc +++ b/src/core/bindings/module_helpers.cc @@ -2,6 +2,10 @@ #include "ns3/ref-count-base.h" #include +#if PY_VERSION_HEX >= 0x03000000 +# define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask +# define PyString_FromStringAndSize PyUnicode_FromStringAndSize +#endif namespace { diff --git a/src/core/bindings/modulegen__gcc_LP64.py b/src/core/bindings/modulegen__gcc_LP64.py index c86b45416..575086a8a 100644 --- a/src/core/bindings/modulegen__gcc_LP64.py +++ b/src/core/bindings/modulegen__gcc_LP64.py @@ -2474,10 +2474,10 @@ def register_Ns3SystemThread_methods(root_module, cls): return def register_Ns3Time_methods(root_module, cls): - #cls.add_binary_numeric_operator('*', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right')) + cls.add_binary_numeric_operator('*', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right')) cls.add_binary_numeric_operator('+', root_module['ns3::Time'], root_module['ns3::Time'], param('ns3::Time const &', u'right')) cls.add_binary_numeric_operator('-', root_module['ns3::Time'], root_module['ns3::Time'], param('ns3::Time const &', u'right')) - #cls.add_binary_numeric_operator('/', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right')) + cls.add_binary_numeric_operator('/', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right')) cls.add_binary_comparison_operator('<') cls.add_binary_comparison_operator('>') cls.add_binary_comparison_operator('!=') diff --git a/src/core/bindings/modulegen_customizations.py b/src/core/bindings/modulegen_customizations.py index c76d318da..2835090b5 100644 --- a/src/core/bindings/modulegen_customizations.py +++ b/src/core/bindings/modulegen_customizations.py @@ -13,77 +13,6 @@ import warnings from pybindgen.typehandlers.base import CodeGenerationError -# 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+' *' - -# 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 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:])) - -# 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 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 - - class ArgvParam(Parameter): """ Converts a python list-of-strings argument to a pair of 'int argc, @@ -123,11 +52,21 @@ PyObject *item = PyList_GET_ITEM(%(py_name)s, %(idx)s); ''' % vars()) #wrapper.before_call.write_error_check('item == NULL') wrapper.before_call.write_error_check( - '!PyString_Check(item)', + '\n' + '#if PY_VERSION_HEX >= 0x03000000\n' + '!PyUnicode_Check(item)\n' + '#else\n' + '!PyString_Check(item)\n' + '#endif\n', failure_cleanup=('PyErr_SetString(PyExc_TypeError, ' '"argument %s must be a list of strings");') % self.name) wrapper.before_call.write_code( - '%s[%s] = PyString_AsString(item);' % (name, idx)) + '#if PY_VERSION_HEX >= 0x03000000\n' + '{var}[{idx}] = PyUnicode_AsUTF8(item);\n' + '#else\n' + '{var}[{idx}] = PyString_AsString(item);\n' + '#endif\n' + .format(var=name, idx=idx)) wrapper.before_call.sink.unindent() wrapper.before_call.write_code('}') wrapper.before_call.write_code('%s = PyList_Size(%s);' % (argc_var, py_name)) @@ -136,165 +75,6 @@ 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. -# """ - -# 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_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; -# } - -# ''' % (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) - -# 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=[]) - -# 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 - -# 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) - -# 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_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.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 write_preamble(out): -# pybindgen.write_preamble(out) -# out.writeln("#include \"ns3/everything.h\"") - - def Simulator_customizations(module): Simulator = module['ns3::Simulator'] @@ -327,76 +107,6 @@ def CommandLine_customizations(module): flags=["METH_VARARGS", "METH_KEYWORDS"]) -# def Object_customizations(module): -# ## --------------------------------------------------------------------- -# ## Here we generate custom constructor code for all classes that -# ## derive from ns3::Object. The custom constructors are needed in -# ## order to support kwargs only and to translate kwargs into ns3 -# ## attributes, etc. -# ## --------------------------------------------------------------------- -# Object = module['ns3::Object'] - - -# ## add a GetTypeId method to all generatd helper classes -# def helper_class_hook(helper_class): -# decl = """ -# static ns3::TypeId GetTypeId (void) -# { -# static ns3::TypeId tid = ns3::TypeId ("%s") -# .SetParent< %s > () -# ; -# return tid; -# }""" % (helper_class.name, helper_class.class_.full_name) - -# helper_class.add_custom_method(decl) -# helper_class.add_post_generation_code( -# "NS_OBJECT_ENSURE_REGISTERED (%s);" % helper_class.name) -# Object.add_helper_class_hook(helper_class_hook) - -# def ns3_object_instance_creation_function(cpp_class, code_block, lvalue, -# parameters, construct_type_name): -# assert lvalue -# assert not lvalue.startswith('None') -# if cpp_class.cannot_be_constructed: -# raise CodeGenerationError("%s cannot be constructed (%s)" -# % cpp_class.full_name) -# if cpp_class.incomplete_type: -# raise CodeGenerationError("%s cannot be constructed (incomplete type)" -# % cpp_class.full_name) -# code_block.write_code("%s = new %s(%s);" % (lvalue, construct_type_name, parameters)) -# code_block.write_code("%s->Ref ();" % (lvalue)) - -# def ns3_object_post_instance_creation_function(cpp_class, code_block, lvalue, -# parameters, construct_type_name): -# code_block.write_code("ns3::CompleteConstruct(%s);" % (lvalue, )) - -# Object.set_instance_creation_function(ns3_object_instance_creation_function) -# Object.set_post_instance_creation_function(ns3_object_post_instance_creation_function) - - -# def Attribute_customizations(module): -# # Fix up for the "const AttributeValue &v = EmptyAttribute()" -# # case, as used extensively by helper classes. - -# # Here's why we need to do this: pybindgen.gccxmlscanner, when -# # scanning parameter default values, is only provided with the -# # value as a simple C expression string. (py)gccxml does not -# # report the type of the default value. - -# # As a workaround, here we iterate over all parameters of all -# # methods of all classes and tell pybindgen what is the type of -# # the default value for attributes. - -# for cls in module.classes: -# for meth in cls.get_all_methods(): -# for param in meth.parameters: -# if isinstance(param, cppclass.CppClassRefParameter): -# if param.cpp_class.name == 'AttributeValue' \ -# and param.default_value is not None \ -# and param.default_value_type is None: -# param.default_value_type = 'ns3::EmptyAttributeValue' - - def TypeId_customizations(module): TypeId = module['ns3::TypeId'] TypeId.add_custom_method_wrapper("LookupByNameFailSafe", "_wrap_TypeId_LookupByNameFailSafe", diff --git a/src/fd-net-device/bindings/modulegen_customizations.py b/src/fd-net-device/bindings/modulegen_customizations.py index 3169505ee..e56ab52bd 100644 --- a/src/fd-net-device/bindings/modulegen_customizations.py +++ b/src/fd-net-device/bindings/modulegen_customizations.py @@ -5,7 +5,7 @@ def post_register_types(root_module): if 'EmuFdNetDevice' not in enabled_features: if 'ns3::EmuFdNetDeviceHelper'in root_module: - root_module.classes.remove(root_module['ns3::EmuFdNetDeviceHelper']) + root_module.classes.remove(root_module['ns3::EmuFdNetDeviceHelper']) if 'TapFdNetDevice' not in enabled_features: if 'ns3::TapFdNetDeviceHelper'in root_module: