def add_optional_vector_wrapper_for(mb, variable): if not templates.is_instantiation(variable.decl_type.decl_string): return False name, args = templates.split(variable.decl_type.decl_string) if not name == '::boost::optional': return False assert (len(args) == 1) vec, v_type = templates.split(args[0]) mb.add_registration_code( textwrap.dedent(""" bp::class_<{optional}>("{optional}", bp::init<>()) // support default non-construct init .def("is_initialized", &{optional}::is_initialized) .def("value", &{optional}::value, bp::return_internal_reference<>()) .add_property("access", +[]({optional} const & self){{return *self;}}, +[]({optional} self , bp::object& value) {{ auto& vect = *self; vect.clear(); for ( auto it = bp::stl_input_iterator< {v_type} > (value); it != bp::stl_input_iterator< {v_type} > (); it++) {{ vect.push_back(*it); }} self = vect; }} ) ; ; """).format(optional=variable.decl_type.decl_string, alias=args[0], v_type=v_type[0])) return True
def scan_callback_classes(module_parser, callback_classes_file): callback_classes_file.write("callback_classes = [\n") for cls in module_parser.module_namespace.classes(function=module_parser.location_filter, recursive=False): if not cls.name.startswith("Callback<"): continue assert templates.is_instantiation(cls.decl_string), "%s is not a template instantiation" % cls dummy_cls_name, template_parameters = templates.split(cls.decl_string) callback_classes_file.write(" %r,\n" % template_parameters) callback_classes_file.write("]\n")
def add_variant_converters_for(mb, cl): """ Register to-python converters for boost::variant objects. (will copy contained type, see pywrap/variant_converter.hpp) Somehow mb.namespace('::boost').classes(allow_empty=True) does not contain the boost::variant class in the project this function was developed for, as a workaround we use: for td in namespace.typedefs(allow_empty=True): if not classes.add_variant_converters_for(mb, td.target_decl): continue # do other things with boost::variant class """ if not templates.is_instantiation(cl.decl_string): return False name, args = templates.split(cl.decl_string) if not name == '::boost::variant': return False # Normally one would like to use cl.include_files.append() here, but # when "cl=td.target_decl", cl points to a # pyplusplus.decl_wrappers.class_wrapper.class_declaration_t # instead of a pyplusplus.decl_wrappers.class_wrapper.class_t object. mb.add_declaration_code('#include "pywrap/variant_converter.hpp"\n') mb.add_registration_code( textwrap.dedent(""" typedef {variant} {alias}; bp::to_python_converter<{alias}, variant_to_object<{alias}> >(); """).format(variant=cl.decl_string, alias=cl.alias)) for arg in args: if arg == 'boost::detail::variant::void_': continue mb.add_registration_code( textwrap.dedent(""" bp::implicitly_convertible<{from_type}, {variant}>(); """).format(variant=cl.alias, from_type=arg)) return True
def __call__(self, module_parser, pygccxml_definition, global_annotations, parameter_annotations): try: ns3_header = get_ns3_relative_path(pygccxml_definition.location.file_name) except ValueError: # the header is not from ns3 return # ignore the definition, it's not ns-3 def. definition_module = self.headers_map[ns3_header] ## Note: we don't include line numbers in the comments because ## those numbers are very likely to change frequently, which would ## cause needless changes, since the generated python files are ## kept under version control. #global_annotations['pygen_comment'] = "%s:%i: %s" % \ # (ns3_header, pygccxml_definition.location.line, pygccxml_definition) global_annotations['pygen_comment'] = "%s (module %r): %s" % \ (ns3_header, definition_module, pygccxml_definition) ## handle ns3::Object::GetObject (left to its own devices, ## pybindgen will generate a mangled name containing the template ## argument type name). if isinstance(pygccxml_definition, member_function_t) \ and pygccxml_definition.parent.name == 'Object' \ and pygccxml_definition.name == 'GetObject': template_args = templates.args(pygccxml_definition.demangled_name) if template_args == ['ns3::Object']: global_annotations['template_instance_names'] = 'ns3::Object=>GetObject' ## Don't wrap Simulator::Schedule* (manually wrapped) if isinstance(pygccxml_definition, member_function_t) \ and pygccxml_definition.parent.name == 'Simulator' \ and pygccxml_definition.name.startswith('Schedule'): global_annotations['ignore'] = None # manually wrapped if isinstance(pygccxml_definition, member_function_t) \ and pygccxml_definition.parent.name == 'Simulator' \ and pygccxml_definition.name == 'Run': global_annotations['ignore'] = True ## http://www.gccxml.org/Bug/view.php?id=9915 if isinstance(pygccxml_definition, calldef_t): for arg in pygccxml_definition.arguments: if arg.default_value is None: continue elif arg.default_value == "ns3::MilliSeconds( )": arg.default_value = "ns3::MilliSeconds(0)" elif arg.default_value == "ns3::Seconds( )": arg.default_value = "ns3::Seconds(0)" ## classes if isinstance(pygccxml_definition, class_t): print >> sys.stderr, pygccxml_definition # no need for helper classes to allow subclassing in Python, I think... #if pygccxml_definition.name.endswith('Helper'): # global_annotations['allow_subclassing'] = 'false' # # If a class is template instantiation, even if the # template was defined in some other module, if a template # argument belongs to this module then the template # instantiation will belong to this module. # if templates.is_instantiation(pygccxml_definition.decl_string): cls_name, template_parameters = templates.split(pygccxml_definition.name) template_parameters_decls = [find_declaration_from_name(module_parser.global_ns, templ_param) for templ_param in template_parameters] #print >> sys.stderr, "********************", cls_name, repr(template_parameters_decls) template_parameters_modules = [] for templ in template_parameters_decls: if not hasattr(templ, 'location'): continue try: h = get_ns3_relative_path(templ.location.file_name) except ValueError: continue template_parameters_modules.append(self.headers_map[h]) for templ_mod in template_parameters_modules: if templ_mod == self.module: definition_module = templ_mod break #print >> sys.stderr, "********************", cls_name, repr(template_parameters_modules) if definition_module != self.module: global_annotations['import_from_module'] = 'ns.%s' % (definition_module.replace('-', '_'),) if pygccxml_definition.decl_string.startswith('::ns3::SimpleRefCount<'): global_annotations['incref_method'] = 'Ref' global_annotations['decref_method'] = 'Unref' global_annotations['peekref_method'] = 'GetReferenceCount' global_annotations['automatic_type_narrowing'] = 'true' return if pygccxml_definition.decl_string.startswith('::ns3::Callback<'): # manually handled in ns3modulegen_core_customizations.py global_annotations['ignore'] = None return if pygccxml_definition.decl_string.startswith('::ns3::TracedCallback<'): global_annotations['ignore'] = None return if pygccxml_definition.decl_string.startswith('::ns3::Ptr<'): # handled by pybindgen "type transformation" global_annotations['ignore'] = None return # table driven class customization try: annotations = type_annotations[pygccxml_definition.decl_string] except KeyError: pass else: global_annotations.update(annotations) ## enums if isinstance(pygccxml_definition, enumeration_t): if definition_module != self.module: global_annotations['import_from_module'] = 'ns.%s' % definition_module ## free functions if isinstance(pygccxml_definition, free_function_t): if definition_module != self.module: global_annotations['ignore'] = None return if pygccxml_definition.name == 'PeekPointer': global_annotations['ignore'] = None return ## table driven methods/constructors/functions customization if isinstance(pygccxml_definition, (free_function_t, member_function_t, constructor_t)): try: annotations = type_annotations[str(pygccxml_definition)] except KeyError: pass else: for key,value in annotations.items(): if key == 'params': parameter_annotations.update (value) del annotations['params'] global_annotations.update(annotations)
def __call__(self, module_parser, pygccxml_definition, global_annotations, parameter_annotations): try: ns3_header = get_ns3_relative_path( pygccxml_definition.location.file_name) except ValueError: return definition_module = self.headers_map[ns3_header] global_annotations['pygen_comment'] = "%s (module %r): %s" % \ (ns3_header, definition_module, pygccxml_definition) if isinstance(pygccxml_definition, member_function_t) \ and pygccxml_definition.parent.name == 'Object' \ and pygccxml_definition.name == 'GetObject': template_args = templates.args(pygccxml_definition.demangled_name) if template_args == ['ns3::Object']: global_annotations[ 'template_instance_names'] = 'ns3::Object=>GetObject' if isinstance(pygccxml_definition, member_function_t) \ and pygccxml_definition.parent.name == 'Simulator' \ and pygccxml_definition.name.startswith('Schedule'): global_annotations['ignore'] = None if isinstance(pygccxml_definition, member_function_t) \ and pygccxml_definition.parent.name == 'Simulator' \ and pygccxml_definition.name == 'Run': global_annotations['ignore'] = True if isinstance(pygccxml_definition, calldef_t): for arg in pygccxml_definition.arguments: if arg.default_value is None: continue elif arg.default_value == "ns3::MilliSeconds( )": arg.default_value = "ns3::MilliSeconds(0)" elif arg.default_value == "ns3::Seconds( )": arg.default_value = "ns3::Seconds(0)" if isinstance(pygccxml_definition, class_t): print >> sys.stderr, pygccxml_definition if templates.is_instantiation(pygccxml_definition.decl_string): cls_name, template_parameters = templates.split( pygccxml_definition.name) template_parameters_decls = [ find_declaration_from_name(module_parser.global_ns, templ_param) for templ_param in template_parameters ] template_parameters_modules = [] for templ in template_parameters_decls: if not hasattr(templ, 'location'): continue try: h = get_ns3_relative_path(templ.location.file_name) except ValueError: continue template_parameters_modules.append(self.headers_map[h]) for templ_mod in template_parameters_modules: if templ_mod == self.module: definition_module = templ_mod break if definition_module != self.module: global_annotations['import_from_module'] = 'ns.%s' % ( definition_module.replace('-', '_'), ) if pygccxml_definition.decl_string.startswith( '::ns3::SimpleRefCount<'): global_annotations['incref_method'] = 'Ref' global_annotations['decref_method'] = 'Unref' global_annotations['peekref_method'] = 'GetReferenceCount' global_annotations['automatic_type_narrowing'] = 'true' return if pygccxml_definition.decl_string.startswith('::ns3::Callback<'): global_annotations['ignore'] = None return if pygccxml_definition.decl_string.startswith( '::ns3::TracedCallback<'): global_annotations['ignore'] = None return if pygccxml_definition.decl_string.startswith('::ns3::Ptr<'): global_annotations['ignore'] = None return try: annotations = type_annotations[pygccxml_definition.decl_string] except KeyError: pass else: global_annotations.update(annotations) if isinstance(pygccxml_definition, enumeration_t): if definition_module != self.module: global_annotations[ 'import_from_module'] = 'ns.%s' % definition_module if isinstance(pygccxml_definition, free_function_t): if definition_module != self.module: global_annotations['ignore'] = None return if pygccxml_definition.name == 'PeekPointer': global_annotations['ignore'] = None return if isinstance(pygccxml_definition, (free_function_t, member_function_t, constructor_t)): try: annotations = type_annotations[str(pygccxml_definition)] except KeyError: pass else: for key, value in annotations.items(): if key == 'params': parameter_annotations.update(value) del annotations['params'] global_annotations.update(annotations)