Python bindings: fix generation of callback wrappers with the newest pybindgen
authorGustavo Carneiro <gjcarneiro@gmail.com>
Sun, 28 Sep 2014 12:39:26 +0100
changeset 10969 99f95535826f
parent 10968 2d29fee2b7b8
child 10970 d94ff887673b
Python bindings: fix generation of callback wrappers with the newest pybindgen
bindings/python/ns3modulegen-modular.py
bindings/python/ns3modulegen_core_customizations.py
bindings/python/wscript
--- a/bindings/python/ns3modulegen-modular.py	Fri Sep 26 15:51:00 2014 -0700
+++ b/bindings/python/ns3modulegen-modular.py	Sun Sep 28 12:39:26 2014 +0100
@@ -103,7 +103,7 @@
         module_customization.post_register_types(root_module)
 
     # register Callback<...> type handlers
-    ns3modulegen_core_customizations.generate_callback_classes(root_module.after_forward_declarations,
+    ns3modulegen_core_customizations.register_callback_classes(root_module.after_forward_declarations,
                                                                callback_classes)
 
     # -----------
@@ -114,20 +114,18 @@
 
     ns3modulegen_core_customizations.Object_customizations(root_module)
     ns3modulegen_core_customizations.Attribute_customizations(root_module)
-
+    ns3modulegen_core_customizations.generate_callback_classes(root_module,
+                                                               callback_classes)
 
     # -----------
     module_apidefs.register_functions(root_module)
-    
+
     if hasattr(module_customization, 'post_register_functions'):
         module_customization.post_register_functions(root_module)
 
-
     # -----------
     root_module.generate(out)
 
 if __name__ == '__main__':
     import sys
     main(sys.argv)
-
-    
--- a/bindings/python/ns3modulegen_core_customizations.py	Fri Sep 26 15:51:00 2014 -0700
+++ b/bindings/python/ns3modulegen_core_customizations.py	Sun Sep 28 12:39:26 2014 +0100
@@ -112,7 +112,73 @@
 
 
 
-def generate_callback_classes(out, callbacks):
+def register_callback_classes(out, callbacks):
+    for callback_impl_num, template_parameters in enumerate(callbacks):
+        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
+
+        class PythonCallbackParameter(Parameter):
+            "Class handlers"
+            CTYPES = [cls_name]
+            print("***** registering callback handler: %r (%r)" % (ctypeparser.normalize_type_string(cls_name), cls_name), file=sys.stderr)
+            DIRECTIONS = [Parameter.DIRECTION_IN]
+            PYTHON_CALLBACK_IMPL_NAME = class_name
+            TEMPLATE_ARGS = template_parameters
+            DISABLED = False
+
+            def convert_python_to_c(self, wrapper):
+                "parses python args to get C++ value"
+                assert isinstance(wrapper, typehandlers.ForwardWrapperBase)
+
+                if self.DISABLED:
+                    raise CodeGenerationError("wrapper could not be generated")
+
+                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 generate_callback_classes(module, callbacks):
+    out = module.after_forward_declarations
     for callback_impl_num, template_parameters in enumerate(callbacks):
         sink = MemoryCodeSink()
         cls_name = "ns3::Callback< %s >" % ', '.join(template_parameters)
@@ -181,68 +247,23 @@
                               Warning)
                 ok = False
         if not ok:
+            try:
+                typehandlers.return_type_matcher.lookup(cls_name)[0].DISABLED = True
+            except typehandlers.TypeLookupError:
+                pass
+            try:
+                typehandlers.param_type_matcher.lookup(cls_name)[0].DISABLED = True
+            except typehandlers.TypeLookupError:
+                pass
             continue
 
         wrapper = CallbackImplProxyMethod(return_type, arguments)
         wrapper.generate(sink, 'operator()', decl_modifiers=[])
-            
+
         sink.unindent()
         sink.writeln('};\n')
+        print("Flushing to ", out, file=sys.stderr)
         sink.flush_to(out)
-        
-        class PythonCallbackParameter(Parameter):
-            "Class handlers"
-            CTYPES = [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
-
-            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):
@@ -374,7 +395,7 @@
     ofstream.add_constructor([Parameter.new("const char *", 'filename'),
                               Parameter.new("::std::ofstream::openmode", 'mode', default_value="std::ios_base::out")])
     ofstream.add_method('close', None, [])
-    
+
     add_std_ios_openmode(module)
 
 
--- a/bindings/python/wscript	Fri Sep 26 15:51:00 2014 -0700
+++ b/bindings/python/wscript	Sun Sep 28 12:39:26 2014 +0100
@@ -13,7 +13,7 @@
 # after = TaskGen.after
 
 ## https://launchpad.net/pybindgen/
-REQUIRED_PYBINDGEN_VERSION = (0, 17, 0, 876)
+REQUIRED_PYBINDGEN_VERSION = (0, 17, 0, 866)
 REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
 
 RUN_ME=-3
@@ -265,7 +265,7 @@
         conf.report_optional_feature("pygccxml", "Python API Scanning Support", False,
                                      "pygccxml too old")
         return
-    
+
 
     ## Check gccxml version
     try:
@@ -409,7 +409,7 @@
     """Generates a 'ns3.py' compatibility module."""
     before = 'cxx'
     color = 'BLUE'
-    
+
     def run(self):
         assert len(self.outputs) == 1
         outfile = file(self.outputs[0].abspath(), "w")