Esempio n. 1
0
def finalize(cls, finalize_pure_virtuals=False):
    """ Attempt to finalize a class by not exposing virtual methods.
         Still exposes in the case of pure virtuals otherwise the class
         could not be instantiated.
   """
    if isinstance(cls, pd.mdecl_wrapper_t):
        for x in cls:
            finalize(x)
    else:
        matcher = pd.virtuality_type_matcher(pd.VIRTUALITY_TYPES.VIRTUAL)
        if finalize_pure_virtuals:
            matcher = matcher | pd.virtuality_type_matcher(
                pd.VIRTUALITY_TYPES.PURE_VIRTUAL)
        members = cls.decls(matcher,
                            decl_type=pd.member_calldef_t,
                            allow_empty=True)
        members.set_virtuality(pd.VIRTUALITY_TYPES.NOT_VIRTUAL)

        cls.decls(pd.access_type_matcher_t(pd.ACCESS_TYPES.PROTECTED),
                  allow_empty=True).exclude()
        cls.decls(pd.access_type_matcher_t(pd.ACCESS_TYPES.PRIVATE),
                  allow_empty=True).exclude()

        wrapper_needs = cls.is_wrapper_needed()
        if len(wrapper_needs):
            print "Finalize failed for: ", cls.name
            for x in wrapper_needs:
                print "   ", x
Esempio n. 2
0
def finalize(cls, finalize_pure_virtuals=False):
   """ Attempt to finalize a class by not exposing virtual methods.
         Still exposes in the case of pure virtuals otherwise the class
         could not be instantiated.
   """
   if isinstance(cls, pd.mdecl_wrapper_t):
      for x in cls:
         finalize(x)
   else:
      matcher = pd.virtuality_type_matcher( pd.VIRTUALITY_TYPES.VIRTUAL )
      if finalize_pure_virtuals:
         matcher = matcher | pd.virtuality_type_matcher( pd.VIRTUALITY_TYPES.PURE_VIRTUAL)
      members = cls.decls( matcher,
                           decl_type=pd.member_calldef_t,
                           allow_empty=True)
      members.set_virtuality( pd.VIRTUALITY_TYPES.NOT_VIRTUAL ) 
      
      cls.decls(pd.access_type_matcher_t(pd.ACCESS_TYPES.PROTECTED),allow_empty=True).exclude()
      cls.decls(pd.access_type_matcher_t(pd.ACCESS_TYPES.PRIVATE),allow_empty=True).exclude()
      
      wrapper_needs = cls.is_wrapper_needed()
      if len(wrapper_needs):
         print "Finalize failed for: ", cls.name
         for x in wrapper_needs:
            print "   ", x
    def parse_class(self, class_decl):
        class_dict = {'name': class_decl.name, 'member_functions': []}
        if class_decl.bases:
            class_dict['bases'] = class_decl.bases[0].declaration_path

        constructors = []
        # constructors
        constructors = []
        query_methods = declarations.access_type_matcher_t('public')
        if hasattr(class_decl, 'constructors'):
            cotrs = class_decl.constructors(function=query_methods,
                                            allow_empty=True, recursive=False,
                                            header_file=self.target_file,
                                            name=class_decl.name)
            for cotr in cotrs:
                constructors.append(self.parse_function(cotr))

        class_dict['constructors'] = constructors

        # class member functions
        member_functions = []
        query_methods = declarations.access_type_matcher_t('public')
        if hasattr(class_decl, 'member_functions'):
            functions = class_decl.member_functions(function=query_methods,
                                                    allow_empty=True, recursive=False,
                                                    header_file=self.target_file)
            for fcn in functions:
                if str(fcn.name) not in [class_decl.name, '~'+class_decl.name]:
                    member_functions.append(self.parse_function(fcn))

        class_dict['member_functions'] = member_functions

        # enums
        class_enums = []
        if hasattr(class_decl, 'variables'):
            enums = class_decl.enumerations(
                allow_empty=True, recursive=False, header_file=self.target_file)
            if enums:
                for _enum in enums:
                    current_enum = {'name': _enum.name, 'values': _enum.values}
                    class_enums.append(current_enum)

        class_dict['enums'] = class_enums

        # variables
        class_vars = []
        query_methods = declarations.access_type_matcher_t('public')
        if hasattr(class_decl, 'variables'):
            variables = class_decl.variables(allow_empty=True, recursive=False, function=query_methods,
                                             header_file=self.target_file)
            if variables:
                for _var in variables:
                    current_var = {
                        'name': _var.name, 'value': _var.value, "has_static": _var.has_static if hasattr(_var, 'has_static') else '0'}
                    class_vars.append(current_var)
        class_dict['vars'] = class_vars

        return class_dict
def typeConversionsOutput(mem_fun,access_type):
   typedef_list=[]
   for td in mem_fun(function=declarations.access_type_matcher_t( access_type ),recursive=False):
      if (not td.is_artificial):
        # entityOutput(td)
         typedef_list.append(td)
   return typedef_list
def dataMembersOutput(mem_fun,access_type):
   typedef_list=[]
   for td in mem_fun(function=declarations.access_type_matcher_t( access_type ),recursive=False):
      typedef_list.append(td)
#      if (mem_fun.__name__ == 'variables'):
#         print('mangled:'+td.get_mangled_name()+'\n')
   return typedef_list
Esempio n. 6
0
def emitClassMethods(c):
    global hSrc, cppSrc, chsSrc
    #chsSrc += '-- *** Constructors\n'
    query = declarations.access_type_matcher_t( 'public' )
    #query = declarations.custom_matcher_t( lambda f: len(f.overloads) == 0) & declarations.access_type_matcher_t( 'public' )
    if not c.is_abstract:
        tc = []
        if c.find_trivial_constructor() != None:
            tc.append(c.find_trivial_constructor())
        ok = False
        cons = [a for a in c.constructors(allow_empty=True, function=query, recursive = False) if not a.is_copy_constructor]
        if len(cons) == 1:
            emitConstructorBinding(c,cons[0])
        else:
            cnt = 0
            for mf in cons: # + tc:
                emitConstructorBinding(c,mf,str(cnt))
                cnt += 1
        emitDestructorBinding(c)
    #chsSrc += '-- *** Methods\n'
    methods = {}
    for mf in c.mem_funs(allow_empty=True, function=query, recursive = False):
        if methods.has_key(mf.name):
            methods[mf.name].append(mf)
        else:
            methods[mf.name] = [mf]
    for mname,mlist in methods.iteritems():
        if len(mlist) == 1:
            emitMethodBinding(c,mlist[0]) # default method is the first one
        else:
            emitMethodBinding(c,mlist[0],'','0')
            cnt = 0
            for mf in mlist:
                emitMethodBinding(c,mf,str(cnt),str(cnt))
                cnt += 1
Esempio n. 7
0
 def test_and_matcher( self ):
     criteria1 = declarations.regex_matcher_t( 'oper.*'
                                                , lambda decl: decl.name )
     criteria2 = declarations.access_type_matcher_t( declarations.ACCESS_TYPES.PUBLIC )
     found = declarations.matcher.find( criteria1 & criteria2, self.global_ns )
     found = filter( lambda d: not d.is_artificial, found )
     self.failUnless( len( found ) <= 6 )
def AutoExclude( mb ):
    """ Automaticaly exclude a range of things that don't convert well from C++ to Python
    """
    global_ns = mb.global_ns
    for ns in NAMESPACES:
        main_ns = global_ns.namespace( ns )
    
        # vars that are static consts but have their values set in the header file are bad
        Remove_Static_Consts ( main_ns )
        
        ## Exclude protected and private that are not pure virtual
        query = declarations.access_type_matcher_t( 'private' ) \
                & ~declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.PURE_VIRTUAL )
        try:
            non_public_non_pure_virtual = main_ns.calldefs( query )
            non_public_non_pure_virtual.exclude()
        except:
            pass
    
        #Virtual functions that return reference could not be overriden from Python
        query = declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.VIRTUAL ) \
                & declarations.custom_matcher_t( lambda decl: declarations.is_reference( decl.return_type ) )
        try:
            main_ns.calldefs( query ).virtuality = declarations.VIRTUALITY_TYPES.NOT_VIRTUAL
        except:
            pass
Esempio n. 9
0
 def test_access_type( self ):       
     criteria = declarations.access_type_matcher_t( declarations.ACCESS_TYPES.PUBLIC )
     public_members = declarations.matcher.find( criteria, self.global_ns )
     if '0.9' in public_members[0].compiler:
         public_members = filter( lambda d: not d.is_artificial, public_members )
         self.failUnless( 16 == len( public_members ) ) 
     else:
         self.failUnless( 20 == len( public_members ) )
 def test_access_type( self ):       
     criteria = declarations.access_type_matcher_t( declarations.ACCESS_TYPES.PUBLIC )
     public_members = declarations.matcher.find( criteria, self.declarations )
     if '0.9' in public_members[0].compiler:
         #2 empty classes, this compiler doesn't generate constructor and copy constructor
         self.failUnless( 15 == len( public_members ) ) 
     else:
         self.failUnless( 19 == len( public_members ) )
Esempio n. 11
0
 def test_and_matcher(self):
     criteria1 = declarations.regex_matcher_t('oper.*',
                                              lambda decl: decl.name)
     criteria2 = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     found = declarations.matcher.find(criteria1 & criteria2,
                                       self.global_ns)
     found = [d for d in found if not d.is_artificial]
     self.assertTrue(len(found) <= 6)
Esempio n. 12
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     if '0.9' in public_members[0].compiler:
         public_members = [d for d in public_members if not d.is_artificial]
         self.failUnless(17 == len(public_members))
     else:
         self.failUnless(21 == len(public_members))
Esempio n. 13
0
 def test_and_matcher(self):
     criteria1 = declarations.regex_matcher_t('oper.*',
                                              lambda decl: decl.name)
     criteria2 = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     found = declarations.matcher.find(criteria1 & criteria2,
                                       self.global_ns)
     found = filter(lambda d: not d.is_artificial, found)
     self.failUnless(len(found) <= 6)
Esempio n. 14
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     if '0.9' in public_members[0].compiler:
         public_members = filter(lambda d: not d.is_artificial,
                                 public_members)
         self.failUnless(16 == len(public_members))
     else:
         self.failUnless(20 == len(public_members))
    def test_or_matcher( self ):
        criteria1 = declarations.regex_matcher_t( 'oper.*'
                                                   , lambda decl: decl.name )
        criteria2 = declarations.access_type_matcher_t( declarations.ACCESS_TYPES.PUBLIC )
        found = declarations.matcher.find( criteria1 | criteria2, self.declarations )

        if '0.9' in found[0].compiler:
            #2 empty classes, this compiler doesn't generate constructor and copy constructor
            self.failUnless( 15 <= len( found ) <= 21) 
        else:
            self.failUnless( 19 <= len( found ) <= 25)
Esempio n. 16
0
 def test_and_matcher(self):
     criteria1 = declarations.regex_matcher_t(
         'oper.*',
         lambda decl: decl.name)
     criteria2 = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     found = declarations.matcher.find(
         criteria1 & criteria2,
         self.global_ns)
     found = [d for d in found if not d.is_artificial]
     self.assertTrue(len(found) <= 6)
Esempio n. 17
0
    def test_or_matcher( self ):
        criteria1 = declarations.regex_matcher_t( 'oper.*'
                                                   , lambda decl: decl.name )
        criteria2 = declarations.access_type_matcher_t( declarations.ACCESS_TYPES.PUBLIC )
        found = declarations.matcher.find( criteria1 | criteria2, self.global_ns )

        if '0.9' in found[0].compiler:
            found = filter( lambda d: not d.is_artificial, found )
            self.failUnless( 15 <= len( found ) <= 21) 
        else:
            self.failUnless( 19 <= len( found ) <= 25)
Esempio n. 18
0
def filter_declarations( mb ):
    global_ns = mb.global_ns
    global_ns.exclude()
    ogrerefapp_ns = global_ns.namespace( 'OgreRefApp' )
    ogrerefapp_ns.include()
    
 
    ## Exclude protected and private that are not pure virtual
    query = ~declarations.access_type_matcher_t( 'public' ) \
            & ~declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.PURE_VIRTUAL )
    non_public_non_pure_virtual = ogrerefapp_ns.calldefs( query )
    non_public_non_pure_virtual.exclude()
Esempio n. 19
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     if "CastXML" in utils.xml_generator:
         public_members = [d for d in public_members if not d.is_artificial]
         self.failUnless(21 == len(public_members))
     if "0.9" in utils.xml_generator:
         public_members = [d for d in public_members if not d.is_artificial]
         self.failUnless(17 == len(public_members))
     else:
         self.failUnless(21 == len(public_members))
Esempio n. 20
0
    def test_or_matcher(self):
        criteria1 = declarations.regex_matcher_t('oper.*',
                                                 lambda decl: decl.name)
        criteria2 = declarations.access_type_matcher_t(
            declarations.ACCESS_TYPES.PUBLIC)
        found = declarations.matcher.find(criteria1 | criteria2,
                                          self.global_ns)

        if '0.9' in found[0].compiler:
            found = filter(lambda d: not d.is_artificial, found)
            self.failUnless(15 <= len(found) <= 21)
        else:
            self.failUnless(19 <= len(found) <= 25)
Esempio n. 21
0
def Auto_Document ( mb, namespace=None ):
    """Indicate that the functions being exposed are declated protected or private in the C++ code
    this should warn people to be careful using them :) """
    global_ns = mb.global_ns
    if namespace:
        main_ns = global_ns.namespace( namespace )
    else:
        main_ns = global_ns
    query = declarations.access_type_matcher_t( 'private' ) 
    for c in main_ns.calldefs( query, allow_empty=True ):
#         print "PRIVATE:", c
        s = c.documentation
        if not s:
            s = ""
        c.documentation="Private declaration.\\n"+s
    query = declarations.access_type_matcher_t( 'protected' ) 
    for c in main_ns.calldefs( query, allow_empty=True ):
#         print "PROTECTED:", c
        s = c.documentation
        if not s:
            s = ""
        c.documentation="Protected declaration.\\n"+s
Esempio n. 22
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     public_members = [d for d in public_members if not d.is_artificial]
     if "CastXML" in utils.xml_generator:
         nbr = len(public_members)
         self.assertTrue(17 == nbr or 21 == nbr)
         if nbr == 21:
             # We are using llvm 3.9, see bug #32. Make sure the 4 names
             # are still there
             ll = ["isa", "flags", "str", "length"]
             for l in ll:
                 self.assertTrue(l in [mbr.name for mbr in public_members])
     else:
         self.assertTrue(17 == len(public_members))
Esempio n. 23
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     public_members = [d for d in public_members if not d.is_artificial]
     if self.xml_generator_from_xml_file.is_castxml:
         nbr = len(public_members)
         self.assertTrue(nbr in [17, 21])
         if nbr == 21:
             # We are using llvm 3.9, see bug #32. Make sure the 4 names
             # are still there
             ll = ["isa", "flags", "str", "length"]
             for l in ll:
                 self.assertTrue(l in [mbr.name for mbr in public_members])
     else:
         self.assertTrue(17 == len(public_members))
Esempio n. 24
0
    def test_or_matcher(self):
        criteria1 = declarations.regex_matcher_t("oper.*",
                                                 lambda decl: decl.name)
        criteria2 = declarations.access_type_matcher_t(
            declarations.ACCESS_TYPES.PUBLIC)
        found = declarations.matcher.find(criteria1 | criteria2,
                                          self.global_ns)

        if "CastXML" in utils.xml_generator:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(len(found) != 35)
        elif "0.9" in utils.xml_generator:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(15 <= len(found) <= 21)
        else:
            self.assertTrue(19 <= len(found) <= 25)
Esempio n. 25
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     public_members = [d for d in public_members if not d.is_artificial]
     if self.xml_generator_from_xml_file.is_castxml:
         nbr = len(public_members)
         self.assertTrue(nbr in [17, 21])
         if nbr == 21:
             # We are using llvm 3.9, see bug #32. Make sure the 4 names
             # are still there
             names = ["isa", "flags", "str", "length"]
             for name in names:
                 self.assertTrue(
                     names in [mbr.name for mbr in public_members])
     else:
         self.assertTrue(17 == len(public_members))
Esempio n. 26
0
    def test_or_matcher(self):
        criteria1 = declarations.regex_matcher_t("oper.*",
                                                 lambda decl: decl.name)
        criteria2 = declarations.access_type_matcher_t(
            declarations.ACCESS_TYPES.PUBLIC)
        found = declarations.matcher.find(criteria1 | criteria2,
                                          self.global_ns)

        if self.xml_generator_from_xml_file.is_castxml:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(len(found) != 35)
        elif self.xml_generator_from_xml_file.is_gccxml_09 or \
                self.xml_generator_from_xml_file.is_gccxml_09_buggy:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(15 <= len(found) <= 21)
        else:
            self.assertTrue(19 <= len(found) <= 25)
Esempio n. 27
0
    def test_or_matcher(self):
        criteria1 = declarations.regex_matcher_t(
            "oper.*",
            lambda decl: decl.name)
        criteria2 = declarations.access_type_matcher_t(
            declarations.ACCESS_TYPES.PUBLIC)
        found = declarations.matcher.find(
            criteria1 | criteria2,
            self.global_ns)

        if "CastXML" in utils.xml_generator:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(len(found) != 35)
        elif "0.9" in utils.xml_generator:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(15 <= len(found) <= 21)
        else:
            self.assertTrue(19 <= len(found) <= 25)
Esempio n. 28
0
    def test_or_matcher(self):
        criteria1 = declarations.regex_matcher_t(
            "oper.*",
            lambda decl: decl.name)
        criteria2 = declarations.access_type_matcher_t(
            declarations.ACCESS_TYPES.PUBLIC)
        found = declarations.matcher.find(
            criteria1 | criteria2,
            self.global_ns)

        if self.xml_generator_from_xml_file.is_castxml:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(len(found) != 35)
        elif self.xml_generator_from_xml_file.is_gccxml_09 or \
                self.xml_generator_from_xml_file.is_gccxml_09_buggy:
            found = [d for d in found if not d.is_artificial]
            self.assertTrue(15 <= len(found) <= 21)
        else:
            self.assertTrue(19 <= len(found) <= 25)
Esempio n. 29
0
def filter_declarations( mb ):	
    """ filter class declarations
    """
    global_ns = mb.global_ns
    global_ns.exclude()
    #global_ns.namespace('std').class_('pair<float, float>').include()
    
    MyGUI_ns = global_ns.namespace( 'MyGUI' )
    MyGUI_ns.include()
    
    global_ns.namespace( 'Ogre' ).class_('SharedPtr<Ogre::Resource>').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('HardwarePixelBufferSharedPtr').include(already_exposed=True)
    
    global_ns.namespace( 'OIS' ).class_('KeyEvent').include(already_exposed=True)
    global_ns.namespace( 'OIS' ).class_('MouseEvent').include(already_exposed=True)	
	
    # Exclude protected and private that are not pure virtual
    query = declarations.access_type_matcher_t( 'private' ) \
            & ~declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.PURE_VIRTUAL )
    MyGUI_ns.calldefs( query, allow_empty=True ).exclude()
Esempio n. 30
0
    def _test_class_membership(self, class_inst, enum_name, access):
        # getting enum through get_members function
        nested_enum1 = class_inst.enum(
            name=enum_name,
            function=declarations.access_type_matcher_t(access))

        # getting enum through declarations property
        nested_enum2 = class_inst.enum(enum_name)

        # it shoud be same object
        self.assertTrue(nested_enum1 is nested_enum2,
                        ("enum accessed through access definition('%s') and " +
                         "through declarations('%s') are different enums " +
                         "or instances.") %
                        (nested_enum1.name, nested_enum2.name))

        # check whether we meaning same class instance
        self.assertTrue(
            class_inst is nested_enum1.parent is nested_enum2.parent,
            'There are 2 or more instances of ns namespace.')
Esempio n. 31
0
    def _test_class_membership(self, class_inst, enum_name, access):
        # getting enum through get_members function
        nested_enum1 = class_inst.enum(
            name=enum_name,
            function=declarations.access_type_matcher_t(access))

        # getting enum through declarations property
        nested_enum2 = class_inst.enum(enum_name)

        # it shoud be same object
        self.failUnless(
            nested_enum1 is nested_enum2,
            ("enum accessed through access definition('%s') and " +
                "through declarations('%s') are different enums " +
                "or instances.") %
            (nested_enum1.name, nested_enum2.name))

        # check whether we meaning same class instance
        self.failUnless(
            class_inst is nested_enum1.parent is nested_enum2.parent,
            'There are 2 or more instances of ns namespace.')
Esempio n. 32
0
 def _process_methods(self):
     if not self.methods_:
         query = declarations.access_type_matcher_t("public")
         hierarchy = self.gcc.recursive_bases
         cls_decls = self.gcc.decls(function=query)
         base_decls = [
             c.related_class.decls(function=query, allow_empty=True) for c in hierarchy if c.access_type == "public"
         ]
         for m in iter_seq([cls_decls] + base_decls):
             if isinstance(m, declarations.enumeration.enumeration_t):
                 try:
                     e = create_decl(m, self.doxyindex, self.opts)
                 except RuntimeError:
                     pass  # ok - not found by doxygen mechanism
                 else:
                     if e.is_exported():
                         raise RuntimeError("Enum '%s' within class '%s' - not allowed." % (m.name, self.gcc.name))
             elif isinstance(m, declarations.calldef.member_function_t):
                 if m.virtuality != "pure virtual":
                     raise RuntimeError("'%s' is not virtual" % m)
                 dm = create_decl(m, self.doxyindex, self.opts)
                 if dm.is_exported():
                     self.methods_.add(dm)
                 else:
                     self.internal_methods_.add(dm)
                 # this is needed as methods in base classes need to know
                 # the class they belong to in the generated (flat) hierarchy
                 dm.gcc_leaf_class = self.gcc
             else:
                 if not isinstance(
                     m,
                     (
                         declarations.calldef.constructor_t,
                         declarations.calldef.destructor_t,
                         declarations.calldef.member_operator_t,
                     ),
                 ):
                     raise RuntimeError(
                         "Unknown declaration '%s' of type '%s' within class '%s'." % (m.name, m, self.gcc.name)
                     )
Esempio n. 33
0
def emitClassMethods(c):
    global hSrc, cppSrc, chsSrc
    #chsSrc += '-- *** Constructors\n'
    query = declarations.access_type_matcher_t('public')
    #query = declarations.custom_matcher_t( lambda f: len(f.overloads) == 0) & declarations.access_type_matcher_t( 'public' )
    if not c.is_abstract:
        tc = []
        if c.find_trivial_constructor() != None:
            tc.append(c.find_trivial_constructor())
        ok = False
        cons = [
            a for a in c.constructors(
                allow_empty=True, function=query, recursive=False)
            if not a.is_copy_constructor
        ]
        if len(cons) == 1:
            emitConstructorBinding(c, cons[0])
        else:
            cnt = 0
            for mf in cons:  # + tc:
                emitConstructorBinding(c, mf, str(cnt))
                cnt += 1
        emitDestructorBinding(c)
    #chsSrc += '-- *** Methods\n'
    methods = {}
    for mf in c.mem_funs(allow_empty=True, function=query, recursive=False):
        if methods.has_key(mf.name):
            methods[mf.name].append(mf)
        else:
            methods[mf.name] = [mf]
    for mname, mlist in methods.iteritems():
        if len(mlist) == 1:
            emitMethodBinding(c, mlist[0])  # default method is the first one
        else:
            emitMethodBinding(c, mlist[0], '', '0')
            cnt = 0
            for mf in mlist:
                emitMethodBinding(c, mf, str(cnt), str(cnt))
                cnt += 1
Esempio n. 34
0
 def _process_methods(self):
     if not self.methods_:
         query = declarations.access_type_matcher_t('public')
         hierarchy = self.gcc.recursive_bases
         cls_decls = self.gcc.decls(function=query)
         base_decls = [
             c.related_class.decls(function=query, allow_empty=True)
             for c in hierarchy if c.access_type == 'public'
         ]
         for m in iter_seq([cls_decls] + base_decls):
             if isinstance(m, declarations.enumeration.enumeration_t):
                 try:
                     e = create_decl(m, self.doxyindex, self.opts)
                 except RuntimeError:
                     pass  # ok - not found by doxygen mechanism
                 else:
                     if e.is_exported():
                         raise RuntimeError(
                             "Enum '%s' within class '%s' - not allowed." %
                             (m.name, self.gcc.name))
             elif isinstance(m, declarations.calldef.member_function_t):
                 if m.virtuality != 'pure virtual':
                     raise RuntimeError("'%s' is not virtual" % m)
                 dm = create_decl(m, self.doxyindex, self.opts)
                 if dm.is_exported():
                     self.methods_.add(dm)
                 else:
                     self.internal_methods_.add(dm)
                 # this is needed as methods in base classes need to know
                 # the class they belong to in the generated (flat) hierarchy
                 dm.gcc_leaf_class = self.gcc
             else:
                 if not isinstance(
                         m, (declarations.calldef.constructor_t,
                             declarations.calldef.destructor_t,
                             declarations.calldef.member_operator_t)):
                     raise RuntimeError(
                         "Unknown declaration '%s' of type '%s' within class '%s'."
                         % (m.name, m, self.gcc.name))
Esempio n. 35
0
def exclude_protected(cls):
   """ Exclude all protected declarations. """
   cls.decls(pd.access_type_matcher_t(pd.ACCESS_TYPES.PROTECTED),allow_empty=True).exclude()
Esempio n. 36
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     public_members = [d for d in public_members if not d.is_artificial]
     self.assertTrue(17 == len(public_members))
Esempio n. 37
0
    def filter_declarations(self):
        code_generator_t.filter_declarations(self)
        # don't export variables that need a wrapper
        self.ompl_ns.variables(lambda decl: decl.is_wrapper_needed()).exclude()
        # make objects printable that have a print function
        self.replace_member_functions(self.ompl_ns.member_functions('print'))
        # print paths as matrices
        self.replace_member_functions(
            self.ompl_ns.member_functions('printAsMatrix'))
        # print debug info
        self.replace_member_functions(
            self.ompl_ns.member_functions('printDebug'))
        self.ompl_ns.member_functions('freeGridMotions').exclude()
        self.ompl_ns.class_('PRM').member_functions(
            'maybeConstructSolution').exclude()
        self.ompl_ns.class_('PRM').member_functions(
            'growRoadmap',
            function=declarations.access_type_matcher_t(
                'protected')).exclude()
        self.ompl_ns.class_('PRM').member_functions(
            'expandRoadmap',
            function=declarations.access_type_matcher_t(
                'protected')).exclude()
        # don't export some internal data structure
        self.ompl_ns.classes('OrderCellsByImportance').exclude()
        # LLVM's clang++ compiler doesn't like exporting this method because
        # the argument type (Grid::Cell) is protected
        self.ompl_ns.member_functions('computeImportance').exclude()
        # add wrappers for boost::function types
        self.add_boost_function('unsigned int()', 'NumNeighborsFn',
                                'Number of neighbors function')
        # self.add_boost_function('std::vector<ompl::geometric::PRM::Vertex>&(const ompl::geometric::PRM::Vertex)',
        #     'ConnectionStrategy', 'Connection strategy')
        self.add_boost_function(
            'bool(const ompl::geometric::PRM::Vertex&, const ompl::geometric::PRM::Vertex&)',
            'ConnectionFilter', 'Connection filter')
        # code generation fails because of same bug in gxxcml that requires us
        # to patch the generated code with workaround_for_gccxml_bug.cmake
        self.ompl_ns.member_functions('getPlannerAllocator').exclude()
        self.ompl_ns.member_functions('setPlannerAllocator').exclude()
        self.ompl_ns.namespace('geometric').class_(
            'SimpleSetup'
        ).add_registration_code(
            'def("setPlannerAllocator", &ompl::geometric::SimpleSetup::setPlannerAllocator)'
        )
        self.ompl_ns.namespace('geometric').class_(
            'SimpleSetup'
        ).add_registration_code(
            'def("getPlannerAllocator", &ompl::geometric::SimpleSetup::getPlannerAllocator, bp::return_value_policy< bp::copy_const_reference >())'
        )

        # The OMPL implementation of PRM uses two threads: one for constructing
        # the roadmap and another for checking for a solution. This causes
        # problems when both threads try to access the python interpreter
        # simultaneously. This is a known limitation of Boost.Python. We
        # therefore use a single-threaded version of PRM in python.
        PRM_cls = self.ompl_ns.class_('PRM')
        PRM_cls.member_function('solve').exclude()
        PRM_cls.add_wrapper_code("""
            virtual ::ompl::base::PlannerStatus solve( ::ompl::base::PlannerTerminationCondition const & ptc ) {
                if( bp::override func_solve = this->get_override( "solve" ) )
                    return func_solve( boost::ref(ptc) );
                else{
                    return default_solve( boost::ref(ptc) );
                }
            }

            ::ompl::base::PlannerStatus default_solve( ::ompl::base::PlannerTerminationCondition const & ptc );
            """)
        PRM_cls.add_declaration_code(
            open('PRM.SingleThreadSolve.cpp', 'r').read())
        PRM_cls.add_registration_code("""def("solve",
            (::ompl::base::PlannerStatus(::ompl::geometric::PRM::*)( ::ompl::base::PlannerTerminationCondition const &))(&PRM_wrapper::solve),
            (::ompl::base::PlannerStatus(PRM_wrapper::*)( ::ompl::base::PlannerTerminationCondition const & ))(&PRM_wrapper::default_solve), bp::arg("ptc") )"""
                                      )
        # exclude PRM*, define it in python to use the single-threaded version
        # of PRM with the k* connection strategy
        self.ompl_ns.class_('PRMstar').exclude()
        # LazyPRM's Vertex type is void* so exclude addMilestone which has return type void*
        self.ompl_ns.class_('LazyPRM').member_function(
            'addMilestone').exclude()

        # Py++ seems to get confused by some methods declared in one module
        # that are *not* overridden in a derived class in another module. The
        # Planner class is defined in ompl::base and two of its virtual methods,
        # setProblemDefinition and checkValidity, and not overridden by most
        # planners. The code below forces Py++ to do the right thing (or at
        # least make it work). It seems rather hacky and there may be a better
        # solution.

        # do this for all planners
        for planner in [
                'EST', 'KPIECE1', 'BKPIECE1', 'LBKPIECE1', 'PRM', 'LazyPRM',
                'PDST', 'LazyRRT', 'RRT', 'RRTConnect', 'TRRT', 'RRTstar',
                'LBTRRT', 'SBL', 'SPARS', 'SPARStwo', 'STRIDE', 'FMT',
                'BITstar'
        ]:
            self.ompl_ns.class_(planner).add_registration_code("""
            def("solve", (::ompl::base::PlannerStatus(::ompl::base::Planner::*)( double ))(&::ompl::base::Planner::solve), (bp::arg("solveTime")) )"""
                                                               )
            if planner != 'PRM':
                # PRM overrides setProblemDefinition, so we don't need to add this code
                self.ompl_ns.class_(planner).add_registration_code("""
                def("setProblemDefinition",&::ompl::base::Planner::setProblemDefinition,
                    &%s_wrapper::default_setProblemDefinition, (bp::arg("pdef")) )"""
                                                                   % planner)
            self.ompl_ns.class_(planner).add_registration_code("""
            def("checkValidity",&::ompl::base::Planner::checkValidity,
                &%s_wrapper::default_checkValidity )""" % planner)

        # do this for all multithreaded planners
        for planner in ['SPARS', 'SPARStwo']:
            cls = self.ompl_ns.class_(planner)
            cls.constructor(
                arg_types=["::ompl::base::SpaceInformationPtr const &"
                           ]).exclude()
            cls.add_registration_code(
                'def(bp::init<ompl::base::SpaceInformationPtr const &>(bp::arg("si")))'
            )
            cls.add_wrapper_code("""
            {0}_wrapper(::ompl::base::SpaceInformationPtr const &si) : ompl::geometric::{0}(si),
                bp::wrapper<ompl::geometric::{0}>()
            {{
                OMPL_WARN("%s: this planner uses multiple threads and might crash if your StateValidityChecker, OptimizationObjective, etc., are allocated within Python.", getName().c_str());
            }}
            """.format(planner))

        # used in SPARS
        self.std_ns.class_('deque<ompl::base::State*>').rename('dequeState')

        # needed to able to set connection strategy for PRM
        # the PRM::Vertex type is typedef-ed to boost::graph_traits<Graph>::vertex_descriptor. This can
        # be equal to an unsigned long or unsigned int, depending on architecture (or version of boost?)
        try:
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').rename(
                'NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned long>'
                                ).rename('NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned long>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned long>').rename(
                'KStarStrategy')
            # used in SPARStwo
            self.std_ns.class_('map<unsigned long, ompl::base::State*>'
                               ).rename('mapVertexToState')
        except:
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').rename(
                'NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned int>').rename(
                'NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned int>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned int>').rename(
                'KStarStrategy')
            # used in SPARStwo
            self.std_ns.class_('map<unsigned int, ompl::base::State*>').rename(
                'mapVertexToState')
Esempio n. 38
0
def generate(defined_symbols, extraIncludes):
    messages.disable(
        messages.W1005 # using a non public variable type for arguments or returns
        , messages.W1006 # `Py++` need your
                         # help to expose function that takes > as argument/returns C++ arrays.
                         # Take a look on "Function Transformation" > functionality and define
                         # the transformation.
        , messages.W1007 # more than 10 args -> BOOST_PYTHON_MAX_ARITY is set
        , messages.W1009 # execution error W1009: The function takes as argument (name=pFunIdx, pos=1) >
                         # non-const reference to Python immutable type - function could not be called > from Python
        , messages.W1014 # "operator*" is not supported. See
        , messages.W1016 # `Py++` does not exports non-const casting operators
        # Warnings 1020 - 1031 are all about why Py++ generates wrapper for class X
        , messages.W1023 # Py++` will generate class wrapper - there are few functions that should be
                         # redefined in class wrapper
        , messages.W1025 # `Py++` will generate class wrapper - class contains "c_" - T* > member variable
        , messages.W1026 # `Py++` will generate class wrapper - class contains "arr_" - T& > member variable
        , messages.W1027 # `Py++` will generate class wrapper - class contains "mat_" - > array member variable
        , messages.W1035 # error. `Py++` can not expose static pointer member variables.
        , messages.W1036 # error. `Py++` can not expose pointer to Python immutable > member variables. This
                         # could be changed in future.
        , messages.W1040 # error. The declaration is unexposed, but there are other > declarations, which
                         # refer to it. This could cause "no to_python converter > found" run
                         # time error
        # This is serious and lead to RuntimeError: `Py++` is going to write different content to the same file
        , messages.W1047 # There are two or more classes that use same > alias("MatElement"). Duplicated aliases causes
                         # few problems, but the main one > is that some of the classes will not
                         # be exposed to Python.Other classes : >
        , messages.W1049 # This method could not be overriden in Python - method returns >
                         # reference to local variable!
        , messages.W1052 # `Py++` will not expose free operator      
        
    )

    logger.debug("Install SRC:  ", os.path.abspath(__file__))
    logger.debug("Execute from: ", os.getcwd())

    sourcedir = os.path.dirname(os.path.abspath(__file__))
    sourceHeader = os.path.abspath(sourcedir + "/" + r"pygimli.h")
    gimliInclude = os.path.dirname(
                         os.path.abspath(sourcedir + "/../src/" + r"gimli.h"))
    settings.includesPaths.append(gimliInclude)

    xml_cached_fc = parser.create_cached_source_fc(
        sourceHeader, settings.module_name + '.cache')
    #xml_cached_fc = parser.create_cached_source_fc(os.path.join(r"pygimli.h"), settings.module_name + '.cache')

    import platform

    defines = ['PYGIMLI_CAST', 'HAVE_BOOST_THREAD_HPP']
    caster = 'gccxml'

    if platform.architecture()[
            0] == '64bit' and platform.system() == 'Windows':

        if sys.platform == 'darwin':
            pass
        else:
            defines.append('_WIN64')
            logger.info('Marking win64 for gccxml')

    for define in [settings.gimli_defines, defined_symbols]:
        if len(define) > 0:
            defines.append(define)

    try:
        if sys.platform == 'win32':
            # os.name == 'nt' (default on my mingw) results in wrong commandline
            # for gccxml
            os.name = 'mingw'
            casterpath = settings.caster_path.replace('\\', '\\\\')
            casterpath = settings.caster_path.replace('/', '\\')
            
            if not 'gccxml' in casterpath:
                caster = 'castxml'
            
            if not '.exe' in casterpath:
                casterpath += '\\' + caster + '.exe'

        else:
            casterpath = settings.caster_path
            if not 'gccxml' in casterpath:
                caster = 'castxml'
            
    except Exception as e:
        logger.info("caster_path=%s" % casterpath)
        logger.info(str(e))
        raise Exception("Problems determine castxml binary")

    settings.includesPaths.insert(0, os.path.abspath(extraIncludes))

    logger.info("caster_path=%s" % casterpath)
    logger.info("working_directory=%s" % settings.gimli_path)
    logger.info("include_paths=%s" % settings.includesPaths)
    logger.info("define_symbols=%s" % defines)
    logger.info("indexing_suite_version=2")


    mb = module_builder.module_builder_t([xml_cached_fc],
                                         gccxml_path=casterpath,
                                         working_directory=settings.gimli_path,
                                         include_paths=settings.includesPaths,
                                         define_symbols=defines,
                                         indexing_suite_version=2,
                                         caster=caster
                                         )

    logger.info("Reading of c++ sources done.")
        
    mb.classes().always_expose_using_scope = True
    mb.calldefs().create_with_signature = True

    global_ns = mb.global_ns
    global_ns.exclude()
    main_ns = global_ns.namespace(MAIN_NAMESPACE)
    main_ns.include()
    

    #for c in main_ns.free_functions():
        ##print(c)
        #if 'pow' in c.name:
            #print(c)
            #print(c.name)
        ##if c.decl_string.startswith('::GIMLI::pow'):
            ##print(c)
            ##print(c.name)
            
    #sys.exit()
                
    logger.info("Apply handmade wrappers.")
    hand_made_wrappers.apply(mb)

    logger.info("Apply custom rvalues.")
    # START manual r-value converters
    rvalue_converters = [
        'register_pytuple_to_rvector3_conversion',
        'register_pysequence_to_rvector_conversion',
        #'register_pysequence_to_bvector_conversion',
        'register_pysequence_to_indexvector_conversion',
        'register_pysequence_to_r3vector_conversion',
        'register_pysequence_to_StdVectorRVector3_conversion',
        #'register_rvector_to_ndarray_conversion',
    ]
    
    for converter in rvalue_converters:
        mb.add_declaration_code('void %s();' % converter)
        mb.add_registration_code('%s();' % converter)

    # END manual r-value converters

    custom_rvalue_path = os.path.join(
        os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp')

    logger.info("Starting to exclude stuff that we don't need or that is known to be spurious.")
    
    exclude(main_ns.variables,
            name=[
                'Triangle6_S1',
                'Triangle6_S2',
                'Triangle6_S3',
                'HexahedronFacesID',
                'Hexahedron20FacesID',
                'TetrahedronFacesID',
                'HexahedronSplit5TetID',
                'HexahedronSplit6TetID',
                'TriPrismFacesID',
                'TriPrimSplit3TetID',
                'NodeCoordinates',
                'EdgeCoordinates',
                'TriCoordinates',
                'QuadCoordinates',
                'TetCoordinates',
                'HexCoordinates',
                'PrismCoordinates',
                'PyramidCoordinates',
                'PyramidFacesID',
                'Tet10NodeSplit',
                'Tet10NodeSplitZienk',
                'Hex20NodeSplit',
                'Prism15NodeSplit',
                'Pyramid13NodeSplit'
                ]
            )

    exclude(main_ns.free_functions,
            return_type=[
                'float *',
                'float &',
                "::GIMLI::__VectorExpr< double, GIMLI::__VectorUnaryExprOp< double, GIMLI::VectorIterator< double >, GIMLI::ABS_ > >"],
            name=[
                'strReplaceBlankWithUnderscore',
                'toStr',
                'toInt',
                'toFloat',
                'toDouble',
                'str',
                'getRowSubstrings',
                'getNonEmptyRow',
                'getSubstrings',
                'abs',
                'type']
            )

    exclude(main_ns.free_operators,
            name=[''],
            return_type=['::std::ostream &', '::std::istream &']
        )

    exclude(main_ns.classes,
            name=['ABS_', 'ACOT', 'ATAN', 'COS', 'COT', 'EXP',
                  'ABS_', 'LOG', 'LOG10', 'SIGN', 'SIN', 'SQRT', 'SQR', 'TAN', 'TANH',
                  'PLUS', 'MINUS', 'MULT', 'DIVID', 'BINASSIGN', 'cerrPtr',
                  'cerrPtrObject', 'coutPtr', 'coutPtrObject', 'deletePtr', 'edge_',
                  'distancePair_', 'IPCMessage', 'PythonGILSave',
                  ]
            )

    exclude(main_ns.member_functions,
            name=['begin',
                  'end',
                  'val'],
            return_type=['']
        )

    exclude(main_ns.member_operators, 
            symbol=[''])
    
    
    for f in main_ns.declarations:
        if isinstance(f, decl_wrappers.calldef_wrapper.free_function_t):
            if (str(f.return_type).find('GIMLI::VectorExpr') != -1):
                f.exclude()
    
    ex = ['::GIMLI::MatrixElement',
          '::GIMLI::__VectorUnaryExprOp',
          '::GIMLI::__VectorBinaryExprOp',
          '::GIMLI::__ValVectorExprOp',
          '::GIMLI::__VectorValExprOp',
          '::GIMLI::__VectorExpr',
          '::GIMLI::Expr',
          '::GIMLI::InversionBase',
          'GIMLI::MatrixElement',
          'GIMLI::__VectorUnaryExprOp',
          'GIMLI::__VectorBinaryExprOp',
          'GIMLI::__ValVectorExprOp',
          'GIMLI::__VectorValExprOp',
          'GIMLI::__VectorExpr',
          'GIMLI::Expr',
          'GIMLI::InversionBase',
          'std::vector<unsigned long',
          ]
    
    for c in main_ns.free_functions():
        for e in ex:
            if c.decl_string.find(e) > -1:
                try:
                    c.exclude()
                    logger.debug("Exclude: " + str(c))
                except:
                    logger.debug("Fail to exclude: " + str(c))
                    
    for c in main_ns.classes():
        for e in ex:
            if c.decl_string.startswith(e):
                try:
                    c.exclude()
                    logger.debug("Exclude: " + c.name)
                except:
                    logger.debug("Fail to exclude: " + c.name)
          
        try:
            for mem in c.constructors():
                for e in ex:
                    if mem.decl_string.find(e) > -1:
                        try:
                            mem.exclude()
                            #logger.info("Exclude: " + str(mem))
                        except:
                            logger.debug("Fail to exclude: " + str(mem))
                            
            for mem in c.member_functions():
                for e in ex:
                    if mem.decl_string.find(e) > -1:
                        try:
                            mem.exclude()
                            #logger.info("Exclude: " + str(mem))
                        except:
                            logger.debug("Fail to exclude: " + str(mem))
        except:
            #print(c, "has no member functions")
            pass
        
        #print('#'*100)
        #print(c, c.name)
        if c.name.startswith('Vector<unsigned long>'):
            #print('         ', c.name)
            for mem in c.constructors():
                #print("mem", mem, mem.decl_string)
                if mem.decl_string.find('( ::GIMLI::Index )') > -1:
                    logger.debug("Exclude: " + str(mem))
                    mem.exclude()
                
                #print("mem", mem)
            
    mb.calldefs(access_type_matcher_t('protected')).exclude()
    mb.calldefs(access_type_matcher_t('private')).exclude()

    # setMemberFunctionCallPolicieByReturn(mb, [ '::GIMLI::Node &'
    #, '::GIMLI::Cell &'
    #, '::GIMLI::Boundary &'
    #, '::GIMLI::Shape &'
    #, '::GIMLI::Node *'
    #, '::GIMLI::Cell *'
    #, '::GIMLI::Boundary *'
    #, '::GIMLI::Shape *'
    #]
    #, call_policies.reference_existing_object)

    setMemberFunctionCallPolicieByReturn(
        mb,
        ['::std::string *', 'float *', 'double *',
         'int *',
         'long *',
         'long int *', 
         'long long int *',
         'unsigned int *',
         'long unsigned int *', 
         'unsigned long long int *',
         '::GIMLI::Index *', '::GIMLI::SIndex *', 'bool *'],
        call_policies.return_pointee_value)

    setMemberFunctionCallPolicieByReturn(mb, ['::std::string &',
                                              'float &',
                                              'double &',
                                              'int &',
                                              'long &',
                                              'long int &',
                                              'long long int &',
                                              'unsigned int &',
                                              'long unsigned int &',
                                              'unsigned long long int &',
                                              '::GIMLI::Index &',
                                              '::GIMLI::SIndex &',
                                              'bool &'
                                              ], call_policies.return_by_value)

    # setMemberFunctionCallPolicieByReturn(mb, ['::GIMLI::VectorIterator<double> &']
    #, call_policies.copy_const_reference)
    # setMemberFunctionCallPolicieByReturn(mb, [
    #,  'double &' ]
    #, call_policies.reference_existing_object)

    # call_policies.return_value_policy(call_policies.reference_existing_object)
    # call_policies.return_value_policy(call_policies.copy_non_const_reference)
    # call_policies.return_value_policy(call_policies.copy_const_reference)

    # addAutoConversions(mb)

   # excludeMemberByReturn(main_ns, ['::DCFEMLib::SparseMatrix<double> &'])
    #main_ns.classes(decl_starts_with(['STLMatrix']), allow_empty=True).exclude()
    #fun = mb.global_ns.member_functions('begin', allow_empty=True)
    # for f in fun:
    # f.exclude()

    # excludeFreeFunctionsByName(main_ns, ['strReplaceBlankWithUnderscore'
    #'toStr', 'toInt', 'toFloat', 'toDouble',
    #'getRowSubstrings', 'getNonEmptyRow', 'getSubstrings' ])

    #excludeFreeFunctionsByReturn(main_ns, [ 'float *', 'float &' ])
    #fun = ns.free_operators(return_type=funct, allow_empty=True)

    #excludeMemberOperators(main_ns, ['++', '--', '*'])

    # exclude all that does not match any predefined callpolicie

    excludeRest = True

    if excludeRest:
        mem_funs = mb.calldefs()

        for mem_fun in mem_funs:
            if mem_fun.call_policies:
                continue
            if not mem_fun.call_policies and \
                    (declarations.is_reference(mem_fun.return_type) or declarations.is_pointer(mem_fun.return_type)):
                # print mem_fun
                # mem_fun.exclude()
                mem_fun.call_policies = call_policies.return_value_policy(
                    call_policies.reference_existing_object)
                # mem_fun.call_policies = \
                #    call_policies.return_value_policy(call_policies.return_pointee_value)
                # mem_fun.call_policies = \
                #    call_policies.return_value_policy(call_policies.return_opaque_pointer)
                # mem_fun.call_policies = \
                #   call_policies.return_value_policy(call_policies.copy_non_const_reference)

    logger.info("Create api documentation from Doxgen comments.")
    # Now it is the time to give a name to our module
    from doxygen import doxygen_doc_extractor
    extractor = doxygen_doc_extractor()

    logger.info("Create code creator.")
    mb.build_code_creator(settings.module_name, doc_extractor=extractor)

    # It is common requirement in software world - each file should have license
    #mb.code_creator.license = '//Boost Software License(http://boost.org/more/license_info.html)'

    # I don't want absolute includes within code
    mb.code_creator.user_defined_directories.append(os.path.abspath('.'))

    # And finally we can write code to the disk
    def ignore(val):
        pass
    logger.info("Create bindings code.")
    mb.split_module('./generated', on_unused_file_found=ignore)

    additional_files = [
        os.path.join(
               os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp'), 
        os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'generators.h'),
        os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'tuples.hpp')]

    logger.info("Add additional files.")
    
    for sourcefile in additional_files:
        p, filename = os.path.split(sourcefile)
        destfile = os.path.join('./generated', filename)

        if not samefile(sourcefile, destfile):
            shutil.copy(sourcefile, './generated')
            logger.info("Updated " +  filename + "as it was missing or out of date")
Esempio n. 39
0
                    print 'exclude <template>', m
                    return False
        if isInPublicScope(m):
            return True
        else:
            print 'exclude', m
            return False
    else:
        print 'exclude', m
        return False


classList = sorted(
    global_ns.classes(header_dir=this_module_dir_path,
                      function=declarations.custom_matcher_t(matcherFun) &
                      (~(declarations.access_type_matcher_t('private')
                         | declarations.access_type_matcher_t('protected')))),
    key=attrgetter('name'))
enumList = sorted(global_ns.enums(header_dir=this_module_dir_path),
                  key=attrgetter('name'))

tyNone = 0
tyPrim = 1
tyGlue = 2
tyObj = 3


def isGlueType(ty):
    ty = declarations.type_traits.remove_reference(
        declarations.type_traits.remove_cv(ty))
    ty = declarations.type_traits.remove_cv(ty)
Esempio n. 40
0
    def get_header_info(self):
        """
        PyGCCXML header code parser
        magic happens here!
        : returns the parsed header data in python dict
        : return dict keys: namespace, class, io_signature, make,
                       properties, methods
        : Can be used as an CLI command or an external API
        """
        gr = self.modname.split('-')[0]
        module = self.modname.split('-')[-1]
        self.parsed_data['module_name'] = module
        generator_path, generator_name = utils.find_xml_generator()
        xml_generator_config = parser.xml_generator_configuration_t(
            xml_generator_path=generator_path,
            xml_generator=generator_name,
            include_paths=self.include_paths,
            compiler='gcc',
            define_symbols=['BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_GENERIC'],
            cflags='-std=c++11')
        decls = parser.parse([self.target_file], xml_generator_config)
        global_namespace = declarations.get_global_namespace(decls)

        # namespace
        try:
            self.parsed_data['namespace'] = []
            ns = global_namespace.namespace(gr)
            if ns is None:
                raise BlockToolException
            main_namespace = ns.namespace(module)
            if main_namespace is None:
                raise BlockToolException('namespace cannot be none')
            self.parsed_data['namespace'] = [gr, module]
            if main_namespace.declarations:
                for _namespace in main_namespace.declarations:
                    if isinstance(_namespace, declarations.namespace_t):
                        if Constants.KERNEL not in str(_namespace):
                            main_namespace = _namespace
                            self.parsed_data['namespace'].append(
                                str(_namespace).split('::')[-1].split(' ')[0])
        except RuntimeError:
            raise BlockToolException(
                'Invalid namespace format in the block header file')

        # class
        try:
            self.parsed_data['class'] = ''
            for _class in main_namespace.declarations:
                if isinstance(_class, declarations.class_t):
                    expected_class_name = self.filename.split('.')[0]
                    if expected_class_name in str(_class):
                        main_class = _class
                        self.parsed_data['class'] = str(_class).split(
                            '::')[2].split(' ')[0]
                        # in more complicated blocks, there are many classes included in this declaration
                        # Break after the first class - safe to assume this is the "main class"?
                        if len(main_class.bases) > 0:
                            self.parsed_data['block_type'] = main_class.bases[
                                0].declaration_path[-1]
                            break
        except RuntimeError:
            raise BlockToolException(
                'Block header namespace {} must consist of a valid class instance'
                .format(module))

        # io_signature, message_ports
        self.parsed_data['io_signature'] = {}
        self.parsed_data['message_port'] = {}
        if os.path.isfile(self.impl_file) and exist_comments(self):
            self.parsed_data['io_signature'] = io_signature(self.impl_file)
            self.parsed_data['message_port'] = message_port(self.impl_file)
            read_comments(self)
        elif os.path.isfile(self.impl_file) and not exist_comments(self):
            self.parsed_data['io_signature'] = io_signature(self.impl_file)
            self.parsed_data['message_port'] = message_port(self.impl_file)
            if self.addcomments:
                add_comments(self)
        elif not os.path.isfile(self.impl_file) and exist_comments(self):
            read_comments(self)
        else:
            self.parsed_data['io_signature'] = {"input": [], "output": []}
            self.parsed_data['message_port'] = self.parsed_data['io_signature']

        # make
        try:
            self.parsed_data['make'] = {}
            self.parsed_data['make']['arguments'] = []
            query_m = declarations.custom_matcher_t(
                lambda mem_fun: mem_fun.name.startswith('make'))
            query_make = query_m & declarations.access_type_matcher_t('public')
            make_func = main_class.member_functions(
                function=query_make,
                allow_empty=True,
                header_file=self.target_file)
            criteria = declarations.calldef_matcher(name='make')
            _make_fun = declarations.matcher.get_single(criteria, main_class)
            _make_fun = str(_make_fun).split('make')[-1].split(')')[0].split(
                '(')[1].lstrip().rstrip().split(',')
            if make_func:
                for arg in make_func[0].arguments:
                    make_arguments = None
                    '''
                    for _arg in _make_fun:
                        if str(arg.name) in _arg:
                            make_arguments = {
                                "name": str(arg.name),
                                "dtype": str(arg.decl_type),
                                "default": ""
                            }
                            if re.findall(r'[-+]?\d*\.\d+|\d+', _arg):
                                make_arguments['default'] = re.findall(
                                    r'[-+]?\d*\.\d+|\d+', _arg)[0]
                            elif re.findall(r'\"(.+?)\"', _arg):
                                make_arguments['default'] = re.findall(
                                    r'\"(.+?)\"', _arg)[0]
                            elif "true" in _arg:
                                make_arguments['default'] = "True"
                            elif "false" in _arg:
                                make_arguments['default'] = "False"
                    '''
                    # In case the search did not find an argument in the inner loop
                    # This happens while parsing digital/symbol_sync_cc.h
                    if make_arguments:
                        self.parsed_data['make']['arguments'].append(
                            make_arguments.copy())
                    else:
                        self.parsed_data['make']['arguments'].append({
                            "name":
                            str(arg.name),
                            "dtype":
                            str(arg.decl_type),
                            "default":
                            arg.
                            default_value  # can we get default argument directly from arg
                        })
        except RuntimeError:
            self.parsed_data['make'] = {}
            self.parsed_data['make']['arguments'] = []

        # setters
        try:
            self.parsed_data['methods'] = []
            query_methods = declarations.access_type_matcher_t('public')
            setters = main_class.member_functions(function=query_methods,
                                                  allow_empty=True,
                                                  header_file=self.target_file)
            getter_arguments = []
            if setters:
                for setter in setters:
                    if str(setter.name).startswith(
                            'set_') and setter.arguments:
                        setter_args = {
                            "name": str(setter.name),
                            "arguments_type": []
                        }
                        for argument in setter.arguments:
                            args = {
                                "name": str(argument.name),
                                "dtype": str(argument.decl_type)
                            }
                            getter_arguments.append(args['name'])
                            setter_args['arguments_type'].append(args.copy())
                        self.parsed_data['methods'].append(setter_args.copy())
        except RuntimeError:
            self.parsed_data['methods'] = []

        # getters
        try:
            self.parsed_data['properties'] = []
            query_properties = declarations.access_type_matcher_t('public')
            getters = main_class.member_functions(function=query_properties,
                                                  allow_empty=True,
                                                  header_file=self.target_file)
            if getters:
                for getter in getters:
                    if not getter.arguments or getter.has_const:
                        getter_args = {
                            "name": str(getter.name),
                            "dtype": str(getter.return_type),
                            "read_only": True
                        }
                        if getter_args['name'] in getter_arguments:
                            getter_args["read_only"] = False
                        self.parsed_data['properties'].append(
                            getter_args.copy())
        except RuntimeError:
            self.parsed_data['properties'] = []

        # all member functions
        # setters and getters do not return all member functions for a block
        try:
            self.parsed_data['member_functions'] = []
            query_methods = declarations.access_type_matcher_t('public')
            functions = main_class.member_functions(
                function=query_methods,
                allow_empty=True,
                header_file=self.target_file)
            if functions:
                for fcn in functions:
                    if str(fcn.name) not in [
                            main_class.name, '~' + main_class.name, 'make'
                    ]:
                        fcn_args = {"name": str(fcn.name), "arguments": []}
                        for argument in fcn.arguments:
                            args = {
                                "name": str(argument.name),
                                "dtype": str(argument.decl_type),
                                "default": argument.default_value
                            }
                            fcn_args['arguments'].append(args.copy())
                        self.parsed_data['member_functions'].append(
                            fcn_args.copy())
        except RuntimeError:
            self.parsed_data['member_functions'] = []

        # documentation
        try:
            _index = None
            header_file = codecs.open(self.target_file, 'r', 'cp932')
            self.parsed_data['docstring'] = re.compile(
                r'//.*?$|/\*.*?\*/',
                re.DOTALL | re.MULTILINE).findall(header_file.read())[2:]
            header_file.close()
            for doc in self.parsed_data['docstring']:
                if Constants.BLOCKTOOL in doc:
                    _index = self.parsed_data['docstring'].index(doc)
            if _index is not None:
                self.parsed_data['docstring'] = self.parsed_data[
                    'docstring'][:_index]
        except:
            self.parsed_data['docstring'] = []

        return self.parsed_data
Esempio n. 41
0
def exclude_protected(cls):
    """ Exclude all protected declarations. """
    cls.decls(pd.access_type_matcher_t(pd.ACCESS_TYPES.PROTECTED),
              allow_empty=True).exclude()
Esempio n. 42
0
def generate(defined_symbols, extraIncludes):
#    messages.disable(
#        messages.W1005 # using a non public variable type for argucments or returns
##           Warnings 1020 - 1031 are all about why Py++ generates wrapper for class X
#        , messages.W1009 # check this
#        , messages.W1014 # check this
#        , messages.W1020
#        , messages.W1021
#        , messages.W1022
#        , messages.W1023
#        , messages.W1024
#        , messages.W1025
#        , messages.W1026
#        , messages.W1027
#        , messages.W1028
#        , messages.W1029
#        , messages.W1030
#        , messages.W1031
#        , messages.W1036 # check this
#)
    
    print("Install SRC:  ", os.path.abspath(__file__))
    print("Execute from: ", os.getcwd())
    
    sourcedir = os.path.dirname(os.path.abspath(__file__))
    sourceHeader = os.path.abspath(sourcedir + "/" + r"pygimli.h")
    gimliInclude = os.path.dirname(os.path.abspath(sourcedir + "/../src/" + r"gimli.h"))
    settings.includesPaths.append(gimliInclude)
            
    xml_cached_fc = parser.create_cached_source_fc(sourceHeader,
                                                   settings.module_name + '.cache')
    #xml_cached_fc = parser.create_cached_source_fc(os.path.join(r"pygimli.h"), settings.module_name + '.cache')
    

    import platform
    
    defines = ['PYGIMLI_GCCXML', 'HAVE_BOOST_THREAD_HPP']

    if platform.architecture()[0] == '64bit' and platform.architecture()[1] != 'ELF':
    
        if sys.platform == 'darwin':
            pass
        else:
            defines.append('_WIN64')
            print('Marking win64 for gccxml')

    for define in [settings.gimli_defines, defined_symbols]:
        if len(define) > 0:
            defines.append(define)

    try:
        if sys.platform == 'win32':
            #os.name == 'nt' (default on my mingw) results in wrong commandline for gccxml
            os.name = 'mingw'
            gccxmlpath = settings.gccxml_path.replace('\\', '\\\\') + '\\\\gccxml.exe'
        else:
            gccxmlpath = settings.gccxml_path
    except Exception as e:
        print (str(e))
        raise Exception("Problems determine gccxml binary")

    settings.includesPaths.insert(0,os.path.abspath(extraIncludes))

    print("gccxml-binary: ", gccxmlpath)
    print("extra-include: ", os.path.abspath(extraIncludes))
    print("gccxml includes: ", settings.includesPaths)
    print("gccxml defines: ", defines)
    
    mb = module_builder.module_builder_t([xml_cached_fc],
                                         gccxml_path=gccxmlpath,
                                         working_directory=settings.gimli_path,
                                         include_paths=settings.includesPaths,
                                         define_symbols=defines,
                                         indexing_suite_version=2)

    mb.classes().always_expose_using_scope = True
    mb.calldefs().create_with_signature = True

    hand_made_wrappers.apply(mb)

    global_ns = mb.global_ns
    global_ns.exclude()
    main_ns = global_ns.namespace(MAIN_NAMESPACE)
    main_ns.include()

    ### START manual r-value converters
    rvalue_converters = [
                            'register_pysequence_to_StdVectorUL_conversion',
                            'register_pytuple_to_rvector3_conversion',
                            'register_pysequence_to_rvector_conversion',
                            'register_pysequence_to_StdVectorRVector3_conversion'
                        ]

    for converter in rvalue_converters:
        mb.add_declaration_code('void %s();' % converter)
        mb.add_registration_code('%s();' % converter)

    ### END manual r-value converters
        
    custom_rvalue_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp')
        
    exclude(main_ns.variables, name = [ 'Triangle6_S1', 'Triangle6_S2', 'Triangle6_S3'
                                        , 'HexahedronFacesID', 'Hexahedron20FacesID'
                                        , 'TetrahedronFacesID'
                                        , 'HexahedronSplit5TetID', 'HexahedronSplit6TetID'
                                        , 'TriPrismFacesID', 'TriPrimSplit3TetID'
                                        , 'NodeCoordinates','EdgeCoordinates' 
                                        , 'TriCoordinates', 'QuadCoordinates' 
                                        , 'TetCoordinates', 'HexCoordinates'
                                        , 'PrismCoordinates', 'PyramidCoordinates', 'PyramidFacesID'
                                        , 'Tet10NodeSplit', 'Tet10NodeSplitZienk'  
                                        , 'Hex20NodeSplit', 'Prism15NodeSplit', 'Pyramid13NodeSplit'
                                        ])

    for f in main_ns.declarations:
        if type(f) == decl_wrappers.calldef_wrapper.free_function_t:
            if (str(f.return_type).find('GIMLI::VectorExpr') != -1):
                f.exclude()

    exclude(main_ns.free_functions,    return_type = [ 'float *', 'float &'
    ,"::GIMLI::__VectorExpr< double, GIMLI::__VectorUnaryExprOp< double, GIMLI::VectorIterator< double >, GIMLI::ABS_ > >"
                                                      ],
                                        name = [ 'strReplaceBlankWithUnderscore'
                                                 , 'toStr', 'toInt', 'toFloat', 'toDouble', 'str'
                                                 , 'getRowSubstrings', 'getNonEmptyRow', 'getSubstrings'
                                                 , 'abs'
                                                 , 'type'
                                                ])

    exclude(main_ns.free_operators,    name = [''],
                                        return_type = ['::std::ostream &', '::std::istream &'])

    exclude(main_ns.classes,           name = [
                                                'ABS_', 'ACOT', 'ATAN', 'COS', 'COT', 'EXP', 'ABS_', 'LOG', 'LOG10', 'SIGN'
                                                ,'SIN', 'SQRT', 'SQR', 'TAN', 'TANH', 'PLUS', 'MINUS', 'MULT', 'DIVID', 'BINASSIGN'
                                                ,'cerrPtr', 'cerrPtrObject', 'coutPtr', 'coutPtrObject', 'deletePtr'
                                                ,'edge_', 'distancePair_'
                                                ,'IPCMessage'
                                                ,'PythonGILSave'
                                                ,'__VectorExpr'
                                                ,'__VectorUnaryExprOp'
                                                ,'__VectorBinaryExprOp'
                                                ,'__VectorValExprOp'
                                                ,'__ValVectorExprOp'
                                                ,'::GIMLI::__VectorValExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::MULT >'
                                                ,'::GIMLI::__VectorBinaryExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::__VectorIterator< double >, GIMLI::MULT>'
                                                ,'::GIMLI::__VectorExpr< double, GIMLI::__VectorBinaryExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::__VectorIterator< double >, GIMLI::MULT > >'
                                                ,'::GIMLI::__VectorExpr< double, GIMLI::__VectorValExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::MULT > >'
                                                ,'::GIMLI::__VectorExpr< double, GIMLI::__VectorUnaryExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::LOG10 > >'
                                                ,'::GIMLI::__VectorExpr< double, GIMLI::__VectorUnaryExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::LOG > >'
                                                ,'::GIMLI::__VectorUnaryExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::LOG10 >'
                                                ,'::GIMLI::__VectorUnaryExprOp< double, GIMLI::__VectorIterator< double >, GIMLI::LOG >'
                                                ,'::GIMLI::__VectorExpr<double, GIMLI::__VectorValExprOp<double, GIMLI::__VectorExpr<double, GIMLI::__ValVectorExprOp<double, GIMLI::__VectorIterator<double >, GIMLI::MULT > >, GIMLI::MULT > >'
    ,'::GIMLI::__VectorValExprOp<double, GIMLI::__VectorExpr<double, GIMLI::__ValVectorExprOp<double, GIMLI::__VectorIterator<double >, GIMLI::MULT > >, GIMLI::MULT >.pypp.hpp',
                                                'GIMLI::Expr<GIMLI::ExprIdentity>'
                                               ])

    exclude(main_ns.member_functions,  name = ['begin', 'end', 'val'],  return_type = [''])

    exclude(main_ns.member_operators,  symbol = [''])

    mb.calldefs(access_type_matcher_t('protected')).exclude()
    mb.calldefs(access_type_matcher_t('private')).exclude()

    #setMemberFunctionCallPolicieByReturn(mb, [ '::GIMLI::Node &'
                                                #, '::GIMLI::Cell &'
                                                #, '::GIMLI::Boundary &'
                                                #, '::GIMLI::Shape &'
                                                #, '::GIMLI::Node *'
                                                #, '::GIMLI::Cell *'
                                                #, '::GIMLI::Boundary *'
                                                #, '::GIMLI::Shape *'
                                        #]
                                        #, call_policies.reference_existing_object)


    setMemberFunctionCallPolicieByReturn(mb, [    '::std::string *', 'float *', 'double *', 'int *', 'long *' 
                                                , 'long long int *', 'unsigned long long int *' 
												, '::GIMLI::Index *']
                                            , call_policies.return_pointee_value)

    #setMemberFunctionCallPolicieByReturn(mb, ['::GIMLI::VectorIterator<double> &']
                                        #, call_policies.copy_const_reference)

    setMemberFunctionCallPolicieByReturn(mb, ['::std::string &'
                                                ,  'double &' ]
                                                , call_policies.return_by_value)

    #setMemberFunctionCallPolicieByReturn(mb, [
                                                #,  'double &' ]
                                                #, call_policies.reference_existing_object)

    #call_policies.return_value_policy(call_policies.reference_existing_object)
    #call_policies.return_value_policy(call_policies.copy_non_const_reference)
    #call_policies.return_value_policy(call_policies.copy_const_reference)


     #addAutoConversions(mb)

   # excludeMemberByReturn(main_ns, ['::DCFEMLib::SparseMatrix<double> &'])
    #main_ns.classes(decl_starts_with(['STLMatrix']), allow_empty=True).exclude()
    #fun = mb.global_ns.member_functions('begin', allow_empty=True)
    #for f in fun:
        #f.exclude()

    #excludeFreeFunctionsByName(main_ns, ['strReplaceBlankWithUnderscore'
                               #'toStr', 'toInt', 'toFloat', 'toDouble',
                               #'getRowSubstrings', 'getNonEmptyRow', 'getSubstrings' ])

    #excludeFreeFunctionsByReturn(main_ns, [ 'float *', 'float &' ])
    #fun = ns.free_operators(return_type=funct, allow_empty=True)


    #excludeMemberOperators(main_ns, ['++', '--', '*'])


    # exclude all that does not match any predefined callpolicie


    excludeRest = True

    if excludeRest:
        mem_funs = mb.calldefs ()

        for mem_fun in mem_funs:
            if mem_fun.call_policies:
                continue
            if not mem_fun.call_policies and \
                (declarations.is_reference(mem_fun.return_type) or declarations.is_pointer (mem_fun.return_type)):
                #print mem_fun
                #mem_fun.exclude()
                mem_fun.call_policies = \
                    call_policies.return_value_policy(call_policies.reference_existing_object)
                #mem_fun.call_policies = \
                #    call_policies.return_value_policy(call_policies.return_pointee_value)
                #mem_fun.call_policies = \
                #    call_policies.return_value_policy(call_policies.return_opaque_pointer)
                #mem_fun.call_policies = \
                 #   call_policies.return_value_policy(call_policies.copy_non_const_reference)


    # Now it is the time to give a name to our module
    from doxygen import doxygen_doc_extractor
    extractor = doxygen_doc_extractor()

    mb.build_code_creator(settings.module_name, doc_extractor=extractor)

    #It is common requirement in software world - each file should have license
    #mb.code_creator.license = '//Boost Software License(http://boost.org/more/license_info.html)'

    #I don't want absolute includes within code
    mb.code_creator.user_defined_directories.append(os.path.abspath('.'))

    #And finally we can write code to the disk
    def ignore(val):
        pass
    mb.split_module('./generated', on_unused_file_found=ignore)
    
    additional_files = [
            os.path.join(os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp'),
            os.path.join(os.path.abspath(os.path.dirname(__file__)), 'generators.h'),
            os.path.join(os.path.abspath(os.path.dirname(__file__)), 'tuples.hpp') 
            ]
            
    for sourcefile in additional_files:
        p,filename = os.path.split(sourcefile)
        destfile = os.path.join('./generated', filename)

        if not samefile(sourcefile, destfile):
            shutil.copy(sourcefile, './generated')
            print("Updated ", filename, "as it was missing or out of date")
Esempio n. 43
0
def generate(defined_symbols, extraIncludes):
    messages.disable(
        messages.W1005  # using a non public variable type for arguments or returns
        , messages.W1006  # `Py++` need your
                          # help to expose function that takes > as argument/returns C++ arrays.
                          # Take a look on "Function Transformation" > functionality and define
                          # the transformation.
        , messages.W1007  # more than 10 args -> BOOST_PYTHON_MAX_ARITY is set
        , messages.W1009  # execution error W1009: The function takes as argument (name=pFunIdx, pos=1) >
                          # non-const reference to Python immutable type - function could not be called > from Python
        , messages.W1014  # "operator*" is not supported. See
        , messages.W1016  # `Py++` does not exports non-const casting operators
        # Warnings 1020 - 1031 are all about why Py++ generates wrapper for class X
        , messages.W1023  # Py++` will generate class wrapper - there are few functions that should be
                          # redefined in class wrapper
        , messages.W1025  # `Py++` will generate class wrapper - class contains "c_" - T* > member variable
        , messages.W1026  # `Py++` will generate class wrapper - class contains "arr_" - T& > member variable
        , messages.W1027  # `Py++` will generate class wrapper - class contains "mat_" - > array member variable
        , messages.W1035  # error. `Py++` can not expose static pointer member variables.
        , messages.W1036  # error. `Py++` can not expose pointer to Python immutable > member variables. This
                          # could be changed in future.
        , messages.W1040  # error. The declaration is unexposed, but there are other > declarations, which
                          # refer to it. This could cause "no to_python converter > found" run
                          # time error
        # This is serious and lead to RuntimeError: `Py++` is going to write different content to the same file
        , messages.W1047 # There are two or more classes that use same > alias("MatElement"). Duplicated aliases causes
                         # few problems, but the main one > is that some of the classes will not
                         # be exposed to Python.Other classes : >
        , messages.W1049  # This method could not be overriden in Python - method returns >
                          # reference to local variable!
        , messages.W1052  # `Py++` will not expose free operator
    )

    logger.debug("Install SRC:  ", os.path.abspath(__file__))
    logger.debug("Execute from: ", os.getcwd())

    sourcedir = os.path.dirname(os.path.abspath(__file__))
    sourceHeader = os.path.abspath(sourcedir + "/" + r"pygimli.h")
    gimliInclude = os.path.dirname(
                         os.path.abspath(sourcedir + "/../src/" + r"gimli.h"))
    settings.includesPaths.append(gimliInclude)

    xml_cached_fc = parser.create_cached_source_fc(
        sourceHeader, settings.module_name + '.cache')

    import platform

    defines = ['PYGIMLI_CAST', 'HAVE_BOOST_THREAD_HPP']
    caster = 'gccxml'
    compiler_path = options.clang

    if platform.system() == 'Windows':
        if platform.architecture()[0] == '64bit':
            #compiler_path = 'C:/msys64/mingw64/bin/clang++'
            if sys.platform == 'darwin':
                pass
            else:
                defines.append('_WIN64')
                defines.append('MS_WIN64')

                logger.info('Marking win64 for gccxml')
        else:
            pass
            #compiler_path = 'C:/msys32/mingw32/bin/clang++'

    if len(compiler_path) == 0:
        compiler_path = None

    for define in [settings.gimli_defines, defined_symbols]:
        if len(define) > 0:
            defines.append(define)

    try:
        if sys.platform == 'win32':
            # os.name == 'nt' (default on my mingw)results in wrong commandline
            # for gccxml
            os.name = 'mingw'
            casterpath = settings.caster_path.replace('\\', '\\\\')
            casterpath = settings.caster_path.replace('/', '\\')

            if 'gccxml' not in casterpath:
                caster = 'castxml'

            if '.exe' not in casterpath:
                casterpath += '\\' + caster + '.exe'

        else:
            casterpath = settings.caster_path
            if 'gccxml' not in casterpath:
                caster = 'castxml'

    except Exception as e:
        logger.info("caster_path=%s" % casterpath)
        logger.info(str(e))
        raise Exception("Problems determine castxml binary")

    settings.includesPaths.insert(0, os.path.abspath(extraIncludes))

    logger.info("caster_path=%s" % casterpath)
    logger.info("working_directory=%s" % settings.gimli_path)
    logger.info("include_paths=%s" % settings.includesPaths)
    logger.info("define_symbols=%s" % defines)
    logger.info("compiler_path=%s" % compiler_path)
    logger.info("indexing_suite_version=2")

    xml_generator_config = parser.xml_generator_configuration_t(
                                        xml_generator=caster,
                                        xml_generator_path=casterpath,
                                        working_directory=settings.gimli_path,
                                        include_paths=settings.includesPaths,
                                        define_symbols=defines,
                                        ignore_gccxml_output=False,
                                        cflags="",
                                        compiler_path=compiler_path)

    mb = module_builder.module_builder_t(
                                [xml_cached_fc],
                                indexing_suite_version=2,
                                xml_generator_config=xml_generator_config
                                )

    logger.info("Reading of c++ sources done.")

    mb.classes().always_expose_using_scope = True
    mb.calldefs().create_with_signature = True

    global_ns = mb.global_ns
    global_ns.exclude()
    main_ns = global_ns.namespace(MAIN_NAMESPACE)
    main_ns.include()

    # for c in main_ns.free_functions():
    #   print(c)
    #   if 'pow' in c.name:
    #       print(c)
    #       print(c.name)
    #   if c.decl_string.startswith('::GIMLI::pow'):
    #       print(c)
    #       print(c.name)
    # sys.exit()

    logger.info("Apply handmade wrappers.")
    try:
        hand_made_wrappers.apply(mb)
    except BaseException as e:
        print(e)

    logger.info("Apply custom rvalues.")
    # START manual r-value converters
    rvalue_converters = [
        'register_pytuple_to_rvector3_conversion',
        'register_pysequence_to_rvector_conversion',
        # 'register_pysequence_to_bvector_conversion',
        'register_pysequence_to_indexvector_conversion',
        'register_pysequence_to_r3vector_conversion',
        'register_pysequence_to_StdVectorRVector3_conversion',
        # 'register_rvector_to_ndarray_conversion',
    ]

    for converter in rvalue_converters:
        mb.add_declaration_code('void %s();' % converter)
        mb.add_registration_code('%s();' % converter)

    # END manual r-value converters

    custom_rvalue_path = os.path.join(
        os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp')

    logger.info("Starting to exclude stuff that we don't need "
                "or that is known to be spurious.")

    exclude(main_ns.variables,
            name=[
                'Triangle6_S1',
                'Triangle6_S2',
                'Triangle6_S3',
                'HexahedronFacesID',
                'Hexahedron20FacesID',
                'TetrahedronFacesID',
                'HexahedronSplit5TetID',
                'HexahedronSplit6TetID',
                'TriPrismFacesID',
                'TriPrimSplit3TetID',
                'NodeCoordinates',
                'EdgeCoordinates',
                'TriCoordinates',
                'QuadCoordinates',
                'TetCoordinates',
                'HexCoordinates',
                'PrismCoordinates',
                'PyramidCoordinates',
                'PyramidFacesID',
                'Tet10NodeSplit',
                'Tet10NodeSplitZienk',
                'Hex20NodeSplit',
                'Prism15NodeSplit',
                'Pyramid13NodeSplit'
                ]
            )

    exclude(main_ns.free_functions,
            return_type=[
                'float *',
                'float &',
                "::GIMLI::__VectorExpr< double, " +
                "GIMLI::__VectorUnaryExprOp< double, " +
                "GIMLI::VectorIterator< double >, GIMLI::ABS_ > >"],
            name=[
                'strReplaceBlankWithUnderscore',
                'toStr',
                'toInt',
                'toFloat',
                'toDouble',
                'str',
                'getRowSubstrings',
                'getNonEmptyRow',
                'getSubstrings',
                'abs',
                'type']
            )

    exclude(main_ns.free_operators,
            name=[''],
            return_type=['::std::ostream &', '::std::istream &']
            )

    exclude(main_ns.classes,
            name=['ABS_', 'ACOT', 'ATAN', 'COS', 'COT', 'EXP',
                  'ABS_', 'LOG', 'LOG10', 'SIGN', 'SIN', 'SQRT', 'SQR',
                  'TAN', 'TANH',
                  'PLUS', 'MINUS', 'MULT', 'DIVID', 'BINASSIGN', 'cerrPtr',
                  'cerrPtrObject', 'coutPtr', 'coutPtrObject', 'deletePtr',
                  'edge_',
                  'distancePair_', 'IPCMessage', 'PythonGILSave',
                  ]
            )

    exclude(main_ns.member_functions,
            name=['begin',
                  'end',
                  'val'],
            return_type=['']
            )

    exclude(main_ns.member_operators,
            symbol=[''])

    for f in main_ns.declarations:
        if isinstance(f, decl_wrappers.calldef_wrapper.free_function_t):
            if (str(f.return_type).find('GIMLI::VectorExpr') != -1):
                f.exclude()

    ex = ['::GIMLI::MatrixElement',
          '::GIMLI::__VectorUnaryExprOp',
          '::GIMLI::__VectorBinaryExprOp',
          '::GIMLI::__ValVectorExprOp',
          '::GIMLI::__VectorValExprOp',
          '::GIMLI::__VectorExpr',
          '::GIMLI::Expr',
          '::GIMLI::InversionBase',
          'GIMLI::MatrixElement',
          'GIMLI::__VectorUnaryExprOp',
          'GIMLI::__VectorBinaryExprOp',
          'GIMLI::__ValVectorExprOp',
          'GIMLI::__VectorValExprOp',
          'GIMLI::__VectorExpr',
          'GIMLI::Expr',
          'GIMLI::InversionBase',
          'std::vector<unsigned long',
          'std::vector<bool',
          'std::vector<double',
          ]

    for c in main_ns.free_functions():
        for e in ex:
            if c.decl_string.find(e) > -1:
                try:
                    c.exclude()
                    logger.debug("Exclude: " + str(c))
                except BaseException as _:
                    logger.debug("Fail to exclude: " + str(c))

    for c in main_ns.classes():
        for e in ex:
            if c.decl_string.startswith(e):
                try:
                    c.exclude()
                    logger.debug("Exclude: " + c.name)
                except BaseException as _:
                    logger.debug("Fail to exclude: " + c.name)

        try:
            for mem in c.variables():
                try:
                    mem.exclude()
                    # logger.info("Exclude: " + str(mem))
                except BaseException as _:
                    logger.debug("Fail to exclude: " + str(mem))
        except BaseException as _:
            # print(c, "has no member functions")
            pass

        try:
            for mem in c.constructors():
                for e in ex:
                    if mem.decl_string.find(e) > -1:
                        try:
                            mem.exclude()
                            # logger.info("Exclude: " + str(mem))
                        except BaseException as _:
                            logger.debug("Fail to exclude: " + str(mem))

            for mem in c.member_functions():
                for e in ex:
                    if mem.decl_string.find(e) > -1:
                        try:
                            mem.exclude()
                            # logger.info("Exclude: " + str(mem))
                        except BaseException as _:
                            logger.debug("Fail to exclude: " + str(mem))



        except BaseException as _:
            # print(c, "has no member functions")
            pass

        # print('#'*100)
        # print(c, c.name)
        if c.name.startswith('Vector<unsigned long>'):
            # print('         ', c.name)
            for mem in c.constructors():
                # print("mem", mem, mem.decl_string)
                if mem.decl_string.find('( ::GIMLI::Index )') > -1:
                    logger.debug("Exclude: " + str(mem))
                    mem.exclude()

                # print("mem", mem)

    try:
        mb.calldefs(access_type_matcher_t('protected')).exclude()
        mb.calldefs(access_type_matcher_t('private')).exclude()
    except BaseException as _:
        pass

    # setMemberFunctionCallPolicieByReturn(mb, [ '::GIMLI::Node &'
    # , '::GIMLI::Cell &'
    # , '::GIMLI::Boundary &'
    # , '::GIMLI::Shape &'
    # , '::GIMLI::Node *'
    # , '::GIMLI::Cell *'
    # , '::GIMLI::Boundary *'
    # , '::GIMLI::Shape *'
    # ]
    # , call_policies.reference_existing_object)

    setMemberFunctionCallPolicieByReturn(
        mb,
        ['::std::string *', 'float *', 'double *',
         'int *',
         'long *',
         'long int *',
         'long long int *',
         'unsigned int *',
         'long unsigned int *',
         'unsigned long long int *',
         'long long unsigned int *',
         '::GIMLI::Index *', '::GIMLI::SIndex *', 'bool *'],
        call_policies.return_pointee_value)

    setMemberFunctionCallPolicieByReturn(mb, ['::std::string &',
                                              'float &',
                                              'double &',
                                              'int &',
                                              'long &',
                                              'long int &',
                                              'long long int &',
                                              'unsigned int &',
                                              'long unsigned int &',
                                              'long long unsigned int &',
                                              'unsigned long long int &',
                                              '::GIMLI::Index &',
                                              '::GIMLI::SIndex &',
                                              'bool &'
                                              ], call_policies.return_by_value)

    # setMemberFunctionCallPolicieByReturn(mb,
    #                                   ['::GIMLI::VectorIterator<double> &']
    # , call_policies.copy_const_reference)
    # setMemberFunctionCallPolicieByReturn(mb, [
    # ,  'double &' ]
    # , call_policies.reference_existing_object)

    # call_policies.return_value_policy(call_policies.reference_existing_object)
    # call_policies.return_value_policy(call_policies.copy_non_const_reference)
    # call_policies.return_value_policy(call_policies.copy_const_reference)

    # addAutoConversions(mb)

    # excludeMemberByReturn(main_ns, ['::DCFEMLib::SparseMatrix<double> &'])
    # fun = mb.global_ns.member_functions('begin', allow_empty=True)
    # for f in fun:
    # f.exclude()

    # excludeFreeFunctionsByName(main_ns, ['strReplaceBlankWithUnderscore'
    # 'toStr', 'toInt', 'toFloat', 'toDouble',
    # 'getRowSubstrings', 'getNonEmptyRow', 'getSubstrings' ])

    # excludeFreeFunctionsByReturn(main_ns, [ 'float *', 'float &' ])
    # fun = ns.free_operators(return_type=funct, allow_empty=True)

    # excludeMemberOperators(main_ns, ['++', '--', '*'])

    # exclude all that does not match any predefined callpolicie

    excludeRest = True

    if excludeRest:
        mem_funs = mb.calldefs()

        for mem_fun in mem_funs:
            if mem_fun.call_policies:
                continue
            if not mem_fun.call_policies and \
                    (declarations.is_reference(mem_fun.return_type) or
                        declarations.is_pointer(mem_fun.return_type)):
                # print mem_fun
                # mem_fun.exclude()
                mem_fun.call_policies = call_policies.return_value_policy(
                    call_policies.reference_existing_object)
                # mem_fun.call_policies = \
                #    call_policies.return_value_policy(call_policies.return_pointee_value)
                # mem_fun.call_policies = \
                #    call_policies.return_value_policy(call_policies.return_opaque_pointer)
                # mem_fun.call_policies = \
                #   call_policies.return_value_policy(call_policies.copy_non_const_reference)

    logger.info("Create api documentation from Doxgen comments.")
    # Now it is the time to give a name to our module
    from doxygen import doxygen_doc_extractor
    extractor = doxygen_doc_extractor()

    logger.info("Create code creator.")
    mb.build_code_creator(settings.module_name, doc_extractor=extractor)

    # It is common requirement in software world-each file should have license
    # mb.code_creator.license = '//Boost Software
    # License(http://boost.org/more/license_info.html)'

    # I don't want absolute includes within code
    mb.code_creator.user_defined_directories.append(os.path.abspath('.'))

    # And finally we can write code to the disk
    def ignore(val):
        pass
    logger.info("Create bindings code.")
    mb.split_module('./generated', on_unused_file_found=ignore)

    additional_files = [
        os.path.join(
            os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp'),
        os.path.join(
            os.path.abspath(os.path.dirname(__file__)), 'generators.h'),
        os.path.join(
            os.path.abspath(os.path.dirname(__file__)), 'tuples.hpp')]

    logger.info("Add additional files.")

    for sourcefile in additional_files:
        p, filename = os.path.split(sourcefile)
        destfile = os.path.join('./generated', filename)

        if not samefile(sourcefile, destfile):
            shutil.copy(sourcefile, './generated')
            logger.info("Updated " + filename +
                        "as it was missing or out of date")
Esempio n. 44
0
def filter_declarations( mb ):
    global_ns = mb.global_ns
    global_ns.exclude()
    
    ogrenewt_ns = global_ns.namespace( 'BasicJoints' )
    ogrenewt_ns.include()
    ogrenewt_ns = global_ns.namespace( 'PrebuiltCustomJoints' )
    ogrenewt_ns.include()
    ogrenewt_ns = global_ns.namespace( 'CollisionPrimitives' )
    ogrenewt_ns.include()
    
    temp_ns = global_ns.namespace( 'Converters' )
    temp_ns.include()
    temp_ns = global_ns.namespace( 'CollisionTools' )
    temp_ns.include()
    temp_ns = global_ns.namespace( 'MomentOfInertia' )
    temp_ns.include()
    
    
    ogrenewt_ns = global_ns.namespace( 'OgreNewt' )
    ogrenewt_ns.include()
    
    ## these need to be excluded due to callback functions - Have been wrapped 
    ogrenewt_ns.class_( "World" ).member_functions("setLeaveWorldCallback").exclude()
    
    
    ogrenewt_ns.class_( "Body" ).member_functions("addBouyancyForce").exclude()
    
    ogrenewt_ns.class_( "Body" ).member_functions("setAutoactiveCallback").exclude()
    ogrenewt_ns.class_( "Body" ).member_functions("setCustomForceAndTorqueCallback").exclude()
    ogrenewt_ns.class_( "Body" ).member_functions("setCustomTransformCallback").exclude()

    ogrenewt_ns.class_( "BodyIterator" ).member_functions("go").exclude()
    global_ns.namespace( 'BasicJoints' ).class_( "Hinge" ).member_functions("setCallback").exclude()
    global_ns.namespace( 'BasicJoints' ).class_( "Slider" ).member_functions("setCallback").exclude()
    global_ns.namespace( 'BasicJoints' ).class_( "Universal" ).member_functions("setCallback").exclude()
    
        
    ## Replaced these with 'useful' functions in the handwrappers - take and return python objects
    ogrenewt_ns.class_( "Body" ).member_functions("setUserData").exclude()
    ogrenewt_ns.class_( "Joint" ).member_functions("setUserData").exclude()
    ogrenewt_ns.class_( "Body" ).member_functions("getUserData").exclude()
    ogrenewt_ns.class_( "Joint" ).member_functions("getUserData").exclude()
    
    ## This one needs a list of vertices given to it
    ogrenewt_ns.class_( "TreeCollision" ).member_functions("addPoly").exclude()
    
     
    # ConvexHull has an overloaded constructor that takes 5 args, one is a pointer to a list of vectors which we can't
    # handle, so we created a helper function caller createConvexHull that takes a python list instead.
    mb.global_ns.namespace ('OgreNewt').class_('ConvexHull').constructor(arg_types=[None,None,None,None,None]).exclude()
       
    ### and we need the free functions 
    for func in ogrenewt_ns.free_functions ():
        ## print "FREE Func:", func.name
        func.include()
            
    ## Exclude protected and private that are not pure virtual
    query = declarations.access_type_matcher_t( 'private' ) \
            & ~declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.PURE_VIRTUAL )
    ogrenewt_ns.calldefs( query, allow_empty=True ).exclude()
    
    
    
    ## Some varibles that we really do need and aren't exposed by default..    
    cls = ogrenewt_ns.class_("ContactCallback")
    cls.variable('m_body0').include()
    cls.variable('m_body1').include()
    cls.variable('m_contact').include()
    cls.variable('m_material').include()
    
    global_ns.namespace( 'Ogre' ).class_('AxisAlignedBox').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('Radian').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('SceneNode').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('IndexData').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('SceneManager').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('Vector3').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('Matrix4').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('Degree').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('Quaternion').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('Node').include(already_exposed=True)
    global_ns.namespace( 'Ogre' ).class_('Serializer').include(already_exposed=True)
Esempio n. 45
0
def emitClassAttributes(c):
    global hSrc, cppSrc, chsSrc
    #chsSrc += '-- *** Attributes\n'
    query = declarations.access_type_matcher_t('public')
    for ma in c.vars(allow_empty=True, function=query, recursive=False):
        emitAttrBinding(c, ma)
Esempio n. 46
0
 def test_access_type(self):
     criteria = declarations.access_type_matcher_t(
         declarations.ACCESS_TYPES.PUBLIC)
     public_members = declarations.matcher.find(criteria, self.global_ns)
     public_members = [d for d in public_members if not d.is_artificial]
     self.assertTrue(17 == len(public_members))
Esempio n. 47
0
builder.decl(
    "::std::vector<lc3_subroutine_call_info, std::allocator<lc3_subroutine_call_info> >"
).include()
builder.decl(
    "::std::vector<lc3_trap_call_info, std::allocator<lc3_trap_call_info> >"
).include()
builder.decl(
    "::std::map<unsigned short, lc3_blackbox_info, std::less<unsigned short>, std::allocator<std::pair<const unsigned short, lc3_blackbox_info> > >"
).include()
builder.decl(
    "::std::map<unsigned short, lc3_breakpoint_info, std::less<unsigned short>, std::allocator<std::pair<const unsigned short, lc3_breakpoint_info> > >"
).include()
builder.decl(
    "::std::map<unsigned short, lc3_watchpoint_info, std::less<unsigned short>, std::allocator<std::pair<const unsigned short, lc3_watchpoint_info> > >"
).include()
builder.decl(
    "::std::map<unsigned short, lc3_memory_stats, std::less<unsigned short>, std::allocator<std::pair<const unsigned short, lc3_memory_stats> > >"
).include()

# Don't export accessors
builder.classes().add_properties(exclude_accessors=True)
# Enclude protected and private methods.
builder.calldefs(declarations.access_type_matcher_t('protected')).exclude()
builder.calldefs(declarations.access_type_matcher_t('private')).exclude()

# Define a name for the module
builder.build_code_creator(module_name="pylc3")

# Writes the C++ interface file
builder.write_module('PyLC3Gen.cpp')
Esempio n. 48
0
def filter_declarations( mb ):
    global_ns = mb.global_ns
    global_ns.exclude()
    
  
    ode_ns = global_ns  ##  Ode doesn't have it's own namespace..  .namespace( 'ode' )
    for cls in ode_ns.classes():
# #         print "Checking ", cls.decl_string
        try:
            if  cls.decl_string[2]=='d' and cls.decl_string[3].isupper():
# #                 print "Including Class:", cls.name
                cls.include()
        except:
            pass
    ## and the dxXXclasses        
    for cls in ode_ns.classes():
# #         print "Checking ", cls.decl_string
        if  cls.decl_string[2:4]=='dx' and cls.decl_string[4].isupper():
# #             print "Including dxClass:", cls.name
            cls.include()
     ## and we'll need the free functions as well
    for funcs in ode_ns.free_functions ():
# #         print "FREE Func:", funcs.name
        if funcs.name[0]=='d' and funcs.name[1].isupper():
# #             print "Including Function", funcs.name
            funcs.include()
            
    for var in ode_ns.variables ():
# #         print "Checking Variable:", var.name
        if len(var.name) > 2:
            if var.name[0]=='d' and var.name[1].isupper():
# #                 print "Including variable", var.name
                var.include()
    for var in ode_ns.typedefs ():
# #         print "Checking typedef:", var.name
        if len(var.name) > 2:
            if var.name[0]=='d' and var.name[1].isupper():
# #                 print "Including typedef", var.name
                var.include()                
#         print "Member Func:", funcs.name
#         if funcs.name[0]=='d':
#             print "Including Member Function", funcs.name
#             funcs.include()

## these either don't exist in the source or have strange arguments
    ignore=(  "dGeomGetBodyNext", "dGeomMoved", "dPrintMatrix",
        "dWorldGetAutoDisableAngularAverageThreshold",
        "dWorldGetAutoDisableLinearAverageThreshold", 
        "dWorldSetAutoDisableAngularAverageThreshold",
        "dWorldSetAutoDisableLinearAverageThreshold" ,
        "dJointAddPUTorque",
        "dGeomTriMeshGetTriangle"
        )
    for cls in ignore:
        try:
            ode_ns.free_function(cls).exclude()
        except:
            pass
       
    # #     
    # in hand wrappers to handle pyobjects...
    ode_ns.class_( "dGeom" ).member_functions( "getData").exclude()
    ode_ns.class_( "dGeom" ).member_functions( "setData").exclude()
    ode_ns.class_( "dBody" ).member_functions( "setData").exclude()
    ode_ns.class_( "dBody" ).member_functions( "getData").exclude()
    
    ode_ns.class_( "dSpace" ).member_functions( "collide").exclude()
    ode_ns.class_( "dFixedJoint" ).member_functions( "create").exclude()

    ## Exclude protected and private that are not pure virtual
    ### need to be careful here as it removes free functions
    query = ( declarations.access_type_matcher_t( 'private' ) | declarations.access_type_matcher_t( 'protected' ) )\
            & ~declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.PURE_VIRTUAL )
    non_public_non_pure_virtual = ode_ns.calldefs( query )
# #     print "TO EXCLUDE:", non_public_non_pure_virtual
    non_public_non_pure_virtual.exclude()
    
    #For some reason Py++ does not honor call policies in this case.
    #You will have to expose them by hand
    dContactGeom = ode_ns.class_( 'dContactGeom' )
    g12 = dContactGeom.variables( lambda d: d.name in ('g1', 'g2' ) )
    g12.exclude()
    #g12.getter_call_policies = call_policies.return_value_policy( call_policies.return_opaque_pointer )

    ode_ns.class_( 'dBox' ).noncopyable = True
    ode_ns.class_( 'dCapsule' ).noncopyable = True
    ode_ns.class_( 'dGeom' ).noncopyable = True
    ode_ns.class_( 'dGeomTransform' ).noncopyable = True
    ode_ns.class_( 'dPlane' ).noncopyable = True
    ode_ns.class_( 'dQuadTreeSpace' ).noncopyable = True
    ode_ns.class_( 'dRay' ).noncopyable = True
    ode_ns.class_( 'dSphere' ).noncopyable = True
Esempio n. 49
0
    def write(self, work_dir):

        if (len(self.class_decls) != len(self.class_full_names)):
            message = 'Not enough class decls added to do write.'
            raise ValueError(message)

        for idx, full_name in enumerate(self.class_full_names):
            short_name = self.class_short_names[idx]
            class_decl = self.class_decls[idx]
            self.hpp_string = ""
            self.cpp_string = ""

            # Add the cpp file header
            self.add_cpp_header(full_name, short_name)

            # Check for struct-enum pattern
            if declarations.is_struct(class_decl):
                enums = class_decl.enumerations(allow_empty=True)
                if len(enums) == 1:
                    replacements = {
                        'class': class_decl.name,
                        'enum': enums[0].name
                    }
                    self.cpp_string += 'void register_{class}_class(py::module &m){{\n'.format(
                        **replacements)
                    self.cpp_string += '    py::class_<{class}> myclass(m, "{class}");\n'.format(
                        **replacements)
                    self.cpp_string += '    py::enum_<{class}::{enum}>(myclass, "{enum}")\n'.format(
                        **replacements)
                    for eachval in enums[0].values:
                        replacements = {
                            'class': class_decl.name,
                            'enum': enums[0].name,
                            'val': eachval[0]
                        }
                        self.cpp_string += '        .value("{val}", {class}::{enum}::{val})\n'.format(
                            **replacements)
                    self.cpp_string += "    .export_values();\n}\n"

                    # Set up the hpp
                    self.add_hpp(short_name)

                    # Do the write
                    self.write_files(work_dir, short_name)
                continue

            # Define any virtual function overloads
            methods_needing_override = self.add_virtual_overides(
                class_decl, short_name)

            # Add overrides if needed
            overrides_string = ""
            if len(methods_needing_override) > 0:
                overrides_string = ', ' + short_name + '_Overloads'

            # Add smart ptr support if needed
            smart_pointer_handle = self.class_info.hierarchy_attribute(
                'smart_ptr_type')
            ptr_support = ""
            if self.has_shared_ptr and smart_pointer_handle is not None:
                ptr_support = ', ' + smart_pointer_handle + '<' + short_name + ' > '

            # Add base classes if needed
            bases = ""
            for eachBase in class_decl.bases:
                cleaned_base = eachBase.related_class.name.replace(" ", "")
                exposed = any(cleaned_base in t.replace(" ", "")
                              for t in self.exposed_class_full_names)
                public = not eachBase.access_type == "private"
                if exposed and public:
                    bases += ', ' + eachBase.related_class.name + " "

            # Add the class refistration
            class_definition_dict = {
                'short_name': short_name,
                'overrides_string': overrides_string,
                'ptr_support': ptr_support,
                'bases': bases
            }
            class_definition_template = self.wrapper_templates[
                "class_definition"]
            self.cpp_string += class_definition_template.format(
                **class_definition_dict)

            # Add constructors
            #if not self.is_abstract and not class_decl.is_abstract:
            # No constructors for classes with private pure virtual methods!
            ppv_class = False
            for eachMemberFunction in class_decl.member_functions(
                    allow_empty=True):
                if eachMemberFunction.virtuality == "pure virtual" and eachMemberFunction.access_type == "private":
                    ppv_class = True
                    break

            if not ppv_class:
                query = declarations.access_type_matcher_t('public')
                for eachConstructor in class_decl.constructors(
                        function=query, allow_empty=True):
                    writer = constructor_writer.CppConsturctorWrapperWriter(
                        self.class_info, eachConstructor, class_decl,
                        self.wrapper_templates, short_name)
                    self.cpp_string = writer.add_self(self.cpp_string)

            # Add public member functions
            query = declarations.access_type_matcher_t('public')
            for eachMemberFunction in class_decl.member_functions(
                    function=query, allow_empty=True):
                exlcuded = False
                if self.class_info.excluded_methods is not None:
                    exlcuded = (eachMemberFunction.name
                                in self.class_info.excluded_methods)
                if not exlcuded:
                    writer = method_writer.CppMethodWrapperWriter(
                        self.class_info, eachMemberFunction, class_decl,
                        self.wrapper_templates, short_name)
                    self.cpp_string = writer.add_self(self.cpp_string)

            # Any custom generators
            if self.class_info.custom_generator is not None:
                self.cpp_string += self.class_info.custom_generator.get_class_cpp_def_code(
                    short_name)

            # Close the class definition
            self.cpp_string += '    ;\n}\n'

            # Set up the hpp
            self.add_hpp(short_name)

            # Do the write
            self.write_files(work_dir, short_name)
Esempio n. 50
0
    def redefined_funcs(self):
        """
        returns list of member functions that should be defined in the class wrapper

        It comes useful in 3 tier hierarchy:

        .. code-block:: c++

           struct base{
               virtual void do_nothing() = 0;
           };

           struct derived{
               virtual void do_something() = 0;
           };

           struct concrete{
               virtual void do_nothing(){}
               virtual void do_something(){}
           };

        The wrapper for class `derived`, should define `do_nothing` function,
        otherwise the generated code will not compile
        """

        if isinstance(self._redefined_funcs, list):
            return self._redefined_funcs

        all_included = declarations.custom_matcher_t(
            lambda decl: decl.ignore == False and decl.exportable)
        all_protected = declarations.access_type_matcher_t(
            'protected') & all_included
        all_pure_virtual = declarations.virtuality_type_matcher_t(
            VIRTUALITY_TYPES.PURE_VIRTUAL)
        all_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.VIRTUAL ) \
                      & ( declarations.access_type_matcher_t( 'public' ) \
                          | declarations.access_type_matcher_t( 'protected' ))
        all_not_pure_virtual = ~all_pure_virtual

        query = all_protected | all_pure_virtual
        mf_query = query | all_virtual
        relevant_opers = declarations.custom_matcher_t(
            lambda decl: decl.symbol in ('()', '[]'))
        funcs = []
        defined_funcs = []

        for base in self.recursive_bases:
            if base.access == ACCESS_TYPES.PRIVATE:
                continue
            base_cls = base.related_class

            funcs.extend(
                base_cls.member_functions(mf_query,
                                          recursive=False,
                                          allow_empty=True))
            funcs.extend(
                base_cls.member_operators(relevant_opers & query,
                                          recursive=False,
                                          allow_empty=True))

            defined_funcs.extend(
                base_cls.member_functions(all_not_pure_virtual,
                                          recursive=False,
                                          allow_empty=True))
            defined_funcs.extend(
                base_cls.member_operators(all_not_pure_virtual
                                          & relevant_opers,
                                          recursive=False,
                                          allow_empty=True))

        not_reimplemented_funcs = set()
        is_same_function = declarations.is_same_function
        for f in funcs:
            cls_fs = self.calldefs(name=f.name,
                                   recursive=False,
                                   allow_empty=True)
            for cls_f in cls_fs:
                if is_same_function(f, cls_f):
                    break
            else:
                #should test whether this function has been added or not
                for f_impl in not_reimplemented_funcs:
                    if is_same_function(f, f_impl):
                        if declarations.is_base_and_derived(
                                f_impl.parent, f.parent):
                            #add function from the most derived class
                            not_reimplemented_funcs.remove(f_impl)
                            not_reimplemented_funcs.add(f)
                        break
                else:
                    #should test whether this function is implemented in base class
                    if f.virtuality != VIRTUALITY_TYPES.PURE_VIRTUAL:
                        not_reimplemented_funcs.add(f)
                    else:
                        for f_defined in defined_funcs:
                            if is_same_function(f, f_defined):
                                break
                        else:
                            not_reimplemented_funcs.add(f)
        functions = filter(
            lambda f: (False == f.ignore and True == f.exportable) or
            all_pure_virtual(f), list(not_reimplemented_funcs))

        #Boost.Python is not able to call for non-virtual function, from the base
        #class if there is a virtual function with the same within base class
        #See override_bug tester for more information

        def buggy_bpl_filter(f):
            if f.parent is self:
                return False
            if f.access_type != ACCESS_TYPES.PUBLIC:
                return False
            if f.virtuality != VIRTUALITY_TYPES.NOT_VIRTUAL:
                return False
            #we need to check that we don't have "same" function in this class
            this_funs = self.decls(name=f.name,
                                   decl_type=declarations.calldef_t,
                                   recursive=False,
                                   allow_empty=True)
            for this_f in this_funs:
                if is_same_function(this_f, f):
                    #there is already the function in the class, so no need to redefined it
                    return False
            else:
                return True

        tmp = {}  # id : f
        for redefined_f in functions:
            #redefined is virtual, I am not interested in virtual functions
            for rfo in redefined_f.overloads:
                if id(rfo) in tmp:
                    continue
                if buggy_bpl_filter(rfo):
                    tmp[id(rfo)] = rfo
        functions.extend(tmp.values())

        functions.sort(cmp=lambda f1, f2: cmp((f1.name, f1.location.as_tuple(
        )), (f2.name, f2.location.as_tuple())))

        self._redefined_funcs = functions
        return self._redefined_funcs
Esempio n. 51
0
    def filter_declarations(self, mb):
        mb.global_ns.exclude()
        mb.global_ns.namespace('pyplusplus', recursive=False).include()
        boost_ns = mb.global_ns.namespace('boost', recursive=False)
        boost_ns.namespace('posix_time', recursive=False).include()
        boost_ns.namespace('date_time', recursive=False).include()
        boost_ns.namespace('gregorian', recursive=False).include()
        boost_ns.namespace('local_time', recursive=False).include()
        boost_ns.classes(
            lambda decl: decl.name.startswith('constrained_value<')).include()
        ## Exclude protected and private that are not pure virtual
        query = ~declarations.access_type_matcher_t( 'public' ) \
            & ~declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.PURE_VIRTUAL )
        non_public_non_pure_virtual = boost_ns.calldefs(query)
        non_public_non_pure_virtual.exclude()

        for name in ['month_str_to_ushort', 'from_stream_type', 'parse_date']:
            boost_ns.calldefs(
                lambda decl: decl.name.startswith(name)).exclude()

        to_be_removed = [
            'c_time',
            'duration_traits_long',
            'duration_traits_adapted',
            'posix_time_system_config'  #TODO find out link bug
            ,
            'millisec_posix_time_system_config'
        ]
        boost_ns.classes(lambda decl: decl.name in to_be_removed).exclude()

        starts_with = [
            'time_resolution_traits<', 'counted_time_rep<', 'date_facet<',
            'period_formatter<', 'date_generator_formatter<',
            'special_values_formatter<'
        ]
        for name in starts_with:
            boost_ns.classes(lambda decl: decl.name.startswith(name)).exclude()

        ends_with = ['_impl', '_config']
        for name in ends_with:
            boost_ns.classes(lambda decl: decl.name.endswith(name)).exclude()

        boost_ns.classes(
            lambda decl: decl.alias.endswith('formatter')).exclude()

        #boost.date_time has problem to create local_[micro]sec_clock
        #variable, it has nothing to do with Py++
        empty_classes = ['local_microsec_clock', 'local_sec_clock']
        for alias in empty_classes:
            class_ = boost_ns.class_(lambda decl: decl.alias == alias)
            class_.exclude()
            class_.ignore = False

        for alias in ['microsec_clock', 'second_clock']:
            class_ = boost_ns.class_(lambda decl: decl.alias == alias)
            class_.calldefs().create_with_signature = True

        tdi = mb.class_(lambda decl: decl.alias == 'time_duration_impl')
        tdi_init = tdi.constructor(arg_types=[None, None, None, None],
                                   recursive=False)
        tdi_init.ignore = True
        #next declarations are not exported, but Py++ writes warnings about them:
        boost_ns.operators('<<').exclude()
        boost_ns.operators('>>').exclude()
        boost_ns.operators('=').exclude()
        #next function uses non public class in its definition.
        microsec_clocks = boost_ns.classes(
            lambda decl: decl.name.startswith('microsec_clock<'))
        for mc in microsec_clocks:
            mc.member_functions('create_time').exclude()

        #TODO: add FT
        #next function takes reference to int. This function could not be called
        #from Python. Function transformation feature solves this problem
        tz_db_base = boost_ns.class_(
            lambda decl: decl.name.startswith('tz_db_base<'))
        tz_db_base.member_functions('split_rule_spec').exclude()
Esempio n. 52
0
    def filter_declarations(self):
        code_generator_t.filter_declarations(self)
        # don't export variables that need a wrapper
        self.ompl_ns.variables(lambda decl: decl.is_wrapper_needed()).exclude()
        # make objects printable that have a print function
        self.replace_member_functions(self.ompl_ns.member_functions('print'))
        self.ompl_ns.member_functions('freeGridMotions').exclude()
        self.ompl_ns.class_('PRM').member_functions('haveSolution').exclude()
        self.ompl_ns.class_('PRM').member_functions('growRoadmap',
                function=declarations.access_type_matcher_t('protected')).exclude()
        self.ompl_ns.class_('PRM').member_functions('expandRoadmap',
                function=declarations.access_type_matcher_t('protected')).exclude()
        # don't export some internal data structure
        self.ompl_ns.classes('OrderCellsByImportance').exclude()
        # LLVM's clang++ compiler doesn't like exporting this method because
        # the argument type (Grid::Cell) is protected
        self.ompl_ns.member_functions('computeImportance').exclude()
        # exclude solve() methods that take a "const PlannerTerminationCondition &"
        # as first argument; only keep the solve() that just takes a double argument
        self.ompl_ns.member_functions('solve', arg_types=['::ompl::base::PlannerTerminationCondition const &']).exclude()
        # add wrappers for boost::function types
        self.add_boost_function('unsigned int()',
            'NumNeighborsFn', 'Number of neighbors function')
        # self.add_boost_function('std::vector<ompl::geometric::PRM::Vertex>&(const ompl::geometric::PRM::Vertex)',
        #     'ConnectionStrategy', 'Connection strategy')
        self.add_boost_function('bool(const ompl::geometric::PRM::Vertex&, const ompl::geometric::PRM::Vertex&)',
            'ConnectionFilter', 'Connection filter')
        # code generation fails because of same bug in gxxcml that requires us
        # to patch the generated code with workaround_for_gccxml_bug.cmake
        self.ompl_ns.member_functions('getPlannerAllocator').exclude()
        self.ompl_ns.member_functions('setPlannerAllocator').exclude()
        self.ompl_ns.namespace('geometric').class_('SimpleSetup').add_registration_code(
            'def("setPlannerAllocator", &ompl::geometric::SimpleSetup::setPlannerAllocator)')
        self.ompl_ns.namespace('geometric').class_('SimpleSetup').add_registration_code(
            'def("getPlannerAllocator", &ompl::geometric::SimpleSetup::getPlannerAllocator, bp::return_value_policy< bp::copy_const_reference >())')

        # The OMPL implementation of PRM uses two threads: one for constructing
        # the roadmap and another for checking for a solution. This causes
        # problems when both threads try to access the python interpreter
        # simultaneously. This is a know limitation of Boost.Python. We
        # therefore use a single-threaded version of PRM in python.
        PRM_cls = self.ompl_ns.class_('PRM')
        PRM_cls.add_wrapper_code('ompl::base::PlannerStatus solve(const ompl::base::PlannerTerminationCondition& ptc);')
        PRM_cls.add_declaration_code(open('PRM.SingleThreadSolve.cpp','r').read())
        PRM_cls.add_registration_code('def("solve", &PRM_wrapper::solve)')
        PRM_cls.add_registration_code('def("solve", timed_solve_function_type(&ompl::base::Planner::solve))')

        # Py++ seems to get confused by virtual methods declared in one module
        # that are *not* overridden in a derived class in another module. The
        # Planner class is defined in ompl::base and two of its virtual methods,
        # setProblemDefinition and checkValidity, and not overridden by most
        # planners. The code below forces Py++ to do the right thing (or at
        # least make it work). It seems rather hacky and there may be a better
        # solution.

        # do this for all planners
        for planner in ['EST', 'KPIECE1', 'BKPIECE1', 'LBKPIECE1', 'PRM', 'LazyRRT', 'RRT', 'RRTConnect', 'TRRT', 'SBL']:
            if planner!='PRM':
                # PRM overrides setProblemDefinition, so we don't need to add this code
                self.ompl_ns.class_(planner).add_registration_code("""
                def("setProblemDefinition",&::ompl::base::Planner::setProblemDefinition,
                    &%s_wrapper::default_setProblemDefinition, (bp::arg("pdef")) )""" % planner)
            self.ompl_ns.class_(planner).add_registration_code("""
            def("checkValidity",&::ompl::base::Planner::checkValidity,
                &%s_wrapper::default_checkValidity )""" % planner)

        # needed to able to set connection strategy for PRM
        # the PRM::Vertex type is typedef-ed to boost::graph_traits<Graph>::vertex_descriptor. This can
        # be equal to an unsigned long or unsigned int, depending on architecture (or version of boost?)
        try:
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').rename('NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned long>').rename('NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned long>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned long>').rename('KStarStrategy')
        except:
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').rename('NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned int>').rename('NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned int>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned int>').rename('KStarStrategy')
    def redefined_funcs( self ):
        """returns list of member functions that should be defined in class wrapper

        It comes useful in 3 tier hierarchy:
        struct base{
            virtual void do_nothing() = 0;
        };

        struct derived{
            virtual void do_something() = 0;
        };

        struct concrete{
            virtual void do_nothing(){}
            virtual void do_something(){}
        };

        derived_wrapper should define do_nothing function, otherwise the generated
        code will not compile
        """

        if isinstance( self._redefined_funcs, list ):
            return self._redefined_funcs

        all_included = declarations.custom_matcher_t( lambda decl: decl.ignore == False and decl.exportable )
        all_protected = declarations.access_type_matcher_t( 'protected' ) & all_included
        all_pure_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.PURE_VIRTUAL )
        all_not_pure_virtual = ~all_pure_virtual

        query = all_protected | all_pure_virtual
        relevant_opers = declarations.custom_matcher_t( lambda decl: decl.symbol in ('()', '[]') )
        funcs = set()
        defined_funcs = set()

        for base in self.recursive_bases:
            if base.access == ACCESS_TYPES.PRIVATE:
                continue
            base_cls = base.related_class
            funcs.update( base_cls.member_functions( query, recursive=False, allow_empty=True ) )
            funcs.update( base_cls.member_operators( relevant_opers & query, recursive=False, allow_empty=True ) )

            defined_funcs.update( base_cls.member_functions( all_not_pure_virtual, recursive=False, allow_empty=True ) )
            defined_funcs.update( base_cls.member_operators( all_not_pure_virtual & relevant_opers, recursive=False, allow_empty=True ) )

        not_reimplemented_funcs = set()
        is_same_function = declarations.is_same_function
        for f in funcs:
            cls_fs = self.calldefs( name=f.name, recursive=False, allow_empty=True )
            for cls_f in cls_fs:
                if is_same_function( f, cls_f ):
                    break
            else:
                #should test whether this function has been added or not
                for f_impl in not_reimplemented_funcs:
                    if is_same_function( f, f_impl ):
                        if declarations.is_base_and_derived( f_impl.parent, f.parent ):
                            #add function from the most derived class
                            not_reimplemented_funcs.remove( f_impl )
                            not_reimplemented_funcs.add( f )                       
                        break
                else:
                    #should test whether this function is implemented in base class
                    if f.virtuality != VIRTUALITY_TYPES.PURE_VIRTUAL:
                        not_reimplemented_funcs.add( f )
                    else:
                        for f_defined in defined_funcs:
                            if is_same_function( f, f_defined ):
                                break
                        else:
                            not_reimplemented_funcs.add( f )
        functions = list( not_reimplemented_funcs )
        functions.sort( cmp=lambda f1, f2: cmp( ( f1.name, f1.location.as_tuple() )
                                                , ( f2.name, f2.location.as_tuple() ) ) )
        self._redefined_funcs = functions
        return self._redefined_funcs
Esempio n. 54
0
    def filter_declarations(self):
        code_generator_t.filter_declarations(self)
        # don't export variables that need a wrapper
        self.ompl_ns.variables(lambda decl: decl.is_wrapper_needed()).exclude()
        # make objects printable that have a print function
        self.replace_member_functions(self.ompl_ns.member_functions('print'))
        # print paths as matrices
        self.replace_member_functions(self.ompl_ns.member_functions('printAsMatrix'))
        # print debug info
        self.replace_member_functions(self.ompl_ns.member_functions('printDebug'))
        self.ompl_ns.member_functions('freeGridMotions').exclude()
        self.ompl_ns.class_('PRM').member_functions('maybeConstructSolution').exclude()
        self.ompl_ns.class_('PRM').member_functions('growRoadmap',
                function=declarations.access_type_matcher_t('protected')).exclude()
        self.ompl_ns.class_('PRM').member_functions('expandRoadmap',
                function=declarations.access_type_matcher_t('protected')).exclude()
        # don't export some internal data structure
        self.ompl_ns.classes('OrderCellsByImportance').exclude()
        # LLVM's clang++ compiler doesn't like exporting this method because
        # the argument type (Grid::Cell) is protected
        self.ompl_ns.member_functions('computeImportance').exclude()
        # add wrappers for boost::function types
        self.add_boost_function('unsigned int()',
            'NumNeighborsFn', 'Number of neighbors function')
        # self.add_boost_function('std::vector<ompl::geometric::PRM::Vertex>&(const ompl::geometric::PRM::Vertex)',
        #     'ConnectionStrategy', 'Connection strategy')
        self.add_boost_function('bool(const ompl::geometric::PRM::Vertex&, const ompl::geometric::PRM::Vertex&)',
            'ConnectionFilter', 'Connection filter')
        # code generation fails because of same bug in gxxcml that requires us
        # to patch the generated code with workaround_for_gccxml_bug.cmake
        self.ompl_ns.member_functions('getPlannerAllocator').exclude()
        self.ompl_ns.member_functions('setPlannerAllocator').exclude()
        self.ompl_ns.namespace('geometric').class_('SimpleSetup').add_registration_code(
            'def("setPlannerAllocator", &ompl::geometric::SimpleSetup::setPlannerAllocator)')
        self.ompl_ns.namespace('geometric').class_('SimpleSetup').add_registration_code(
            'def("getPlannerAllocator", &ompl::geometric::SimpleSetup::getPlannerAllocator, bp::return_value_policy< bp::copy_const_reference >())')

        # Py++ seems to get confused by some methods declared in one module
        # that are *not* overridden in a derived class in another module. The
        # Planner class is defined in ompl::base and two of its virtual methods,
        # setProblemDefinition and checkValidity, and not overridden by most
        # planners. The code below forces Py++ to do the right thing (or at
        # least make it work). It seems rather hacky and there may be a better
        # solution.

        # do this for all planners
        for planner in ['EST', 'KPIECE1', 'BKPIECE1', 'LBKPIECE1', 'PRM', 'LazyPRM', 'LazyPRMstar', 'PDST', 'LazyRRT', 'RRT', 'RRTConnect', 'TRRT', 'RRTstar', 'LBTRRT', 'SBL', 'SPARS', 'SPARStwo', 'STRIDE', 'FMT', 'BITstar']:
            try:
                cls = self.ompl_ns.class_(planner)
            except:
                continue
            self.ompl_ns.class_(planner).add_registration_code("""
            def("solve", (::ompl::base::PlannerStatus(::ompl::base::Planner::*)( double ))(&::ompl::base::Planner::solve), (bp::arg("solveTime")) )""")
            if planner!='PRM':
                # PRM overrides setProblemDefinition, so we don't need to add this code
                self.ompl_ns.class_(planner).add_registration_code("""
                def("setProblemDefinition",&::ompl::base::Planner::setProblemDefinition,
                    &%s_wrapper::default_setProblemDefinition, (bp::arg("pdef")) )""" % planner)
            self.ompl_ns.class_(planner).add_registration_code("""
            def("checkValidity",&::ompl::base::Planner::checkValidity,
                &%s_wrapper::default_checkValidity )""" % planner)

        # The OMPL implementation of PRM uses two threads: one for constructing
        # the roadmap and another for checking for a solution. This causes
        # problems when both threads try to access the python interpreter
        # simultaneously. This is a known limitation of Boost.Python. We
        # therefore use a single-threaded version of PRM in python.
        PRM_cls = self.ompl_ns.class_('PRM')
        PRM_cls.member_function('solve').exclude()
        PRM_cls.add_wrapper_code("""
            virtual ::ompl::base::PlannerStatus solve( ::ompl::base::PlannerTerminationCondition const & ptc ) {
                if( bp::override func_solve = this->get_override( "solve" ) )
                    return func_solve( boost::ref(ptc) );
                else{
                    return default_solve( boost::ref(ptc) );
                }
            }

            ::ompl::base::PlannerStatus default_solve( ::ompl::base::PlannerTerminationCondition const & ptc );
            """)
        PRM_cls.add_declaration_code(open('PRM.SingleThreadSolve.cpp','r').read())
        # This needs to be the last registration code added to the PRM_cls to the ugly hack below.
        PRM_cls.add_registration_code("""def("solve",
            (::ompl::base::PlannerStatus(::ompl::geometric::PRM::*)( ::ompl::base::PlannerTerminationCondition const &))(&PRM_wrapper::solve),
            (::ompl::base::PlannerStatus(PRM_wrapper::*)( ::ompl::base::PlannerTerminationCondition const & ))(&PRM_wrapper::default_solve), bp::arg("ptc") );

            // HACK ALERT: closing brace destroys bp::scope, so that PRMstar is not a nested class of PRM
            }
            {
                // wrapper for PRMstar, derived from single-threaded PRM_wrapper
                bp::class_<PRMstar_wrapper, bp::bases< PRM_wrapper >, boost::noncopyable >("PRMstar", bp::init< ompl::base::SpaceInformationPtr const & >( bp::arg("si") ) )
            """)
        # Add wrapper code for PRM*
        PRM_cls.add_declaration_code("""
        class PRMstar_wrapper : public PRM_wrapper
        {
        public:
            PRMstar_wrapper(const ompl::base::SpaceInformationPtr &si) : PRM_wrapper(si, true)
            {
                setName("PRMstar");
                params_.remove("max_nearest_neighbors");
            }
        };
        """)
        # LazyPRM's Vertex type is void* so exclude addMilestone which has return type void*
        self.ompl_ns.class_('LazyPRM').member_function('addMilestone').exclude()
        # avoid difficulties in exporting the return type std::vector<base::PlannerDataPtr>
                # do this for all multithreaded planners
        for planner in ['SPARS', 'SPARStwo']:
            cls = self.ompl_ns.class_(planner)
            cls.constructor(arg_types=["::ompl::base::SpaceInformationPtr const &"]).exclude()
            cls.add_registration_code('def(bp::init<ompl::base::SpaceInformationPtr const &>(bp::arg("si")))')
            cls.add_wrapper_code("""
            {0}_wrapper(::ompl::base::SpaceInformationPtr const &si) : ompl::geometric::{0}(si),
                bp::wrapper<ompl::geometric::{0}>()
            {{
                OMPL_WARN("%s: this planner uses multiple threads and might crash if your StateValidityChecker, OptimizationObjective, etc., are allocated within Python.", getName().c_str());
            }}
            """.format(planner))

        # used in SPARS
        self.std_ns.class_('deque<ompl::base::State*>').rename('dequeState')

        # needed to able to set connection strategy for PRM
        # the PRM::Vertex type is typedef-ed to boost::graph_traits<Graph>::vertex_descriptor. This can
        # be equal to an unsigned long or unsigned int, depending on architecture (or version of boost?)
        try:
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').rename('NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned long>').rename('NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned long>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned long>').rename('KStarStrategy')
            # used in SPARStwo
            self.std_ns.class_('map<unsigned long, ompl::base::State*>').rename('mapVertexToState')
        except:
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').rename('NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned int>').rename('NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned int>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned int>').rename('KStarStrategy')
            # used in SPARStwo
            self.std_ns.class_('map<unsigned int, ompl::base::State*>').rename('mapVertexToState')

        try:
            # Exclude some functions from BIT* that cause some Py++ compilation problems:
            self.ompl_ns.class_('BITstar').member_functions('getEdgeQueue').exclude() #I don't know why this doesn't work.
            self.ompl_ns.class_('BITstar').member_functions('getVertexQueue').exclude() #I don't know why this doesn't work.
        except:
            pass
Esempio n. 55
0
    def filter_declarations(self):
        code_generator_t.filter_declarations(self)
        #self.ompl_ns.namespace('util').exclude()
        # don't export variables that need a wrapper
        self.ompl_ns.variables(lambda decl: decl.is_wrapper_needed()).exclude()
        # make objects printable that have a print function
        self.replace_member_functions(self.ompl_ns.member_functions('print'))
        # print paths as matrices
        self.replace_member_functions(self.ompl_ns.member_functions('printAsMatrix'))
        # print debug info
        self.replace_member_functions(self.ompl_ns.member_functions('printDebug'))
        self.ompl_ns.member_functions('freeGridMotions').exclude()
        self.ompl_ns.class_('PRM').member_functions('maybeConstructSolution').exclude()
        self.ompl_ns.class_('PRM').member_functions('growRoadmap', \
            function=declarations.access_type_matcher_t('protected')).exclude()
        self.ompl_ns.class_('PRM').member_functions('expandRoadmap', \
            function=declarations.access_type_matcher_t('protected')).exclude()
        # don't export some internal data structure
        self.ompl_ns.classes('OrderCellsByImportance').exclude()
        # LLVM's clang++ compiler doesn't like exporting this method because
        # the argument type (Grid::Cell) is protected
        self.ompl_ns.member_functions('computeImportance').exclude()
        # add wrappers for std::function types
        self.add_function_wrapper('unsigned int()', \
            'NumNeighborsFn', 'Number of neighbors function')
        # self.add_function_wrapper(
        # 'std::vector<ompl::geometric::PRM::Vertex>&(const ompl::geometric::PRM::Vertex)',
        #     'ConnectionStrategy', 'Connection strategy')
        self.add_function_wrapper(
            'bool(const ompl::geometric::PRM::Vertex&, const ompl::geometric::PRM::Vertex&)',
            'ConnectionFilter', 'Connection filter')
        # code generation fails to compile, most likely because of a bug in
        # Py++'s generation of exposed_decl.pypp.txt.
        self.ompl_ns.member_functions('getPlannerAllocator').exclude()
        self.ompl_ns.member_functions('setPlannerAllocator').exclude()
        self.ompl_ns.namespace('geometric').class_('SimpleSetup').add_registration_code(
            'def("setPlannerAllocator", &ompl::geometric::SimpleSetup::setPlannerAllocator)')
        self.ompl_ns.namespace('geometric').class_('SimpleSetup').add_registration_code( \
            'def("getPlannerAllocator", &ompl::geometric::SimpleSetup::getPlannerAllocator, ' \
            'bp::return_value_policy< bp::copy_const_reference >())')
        self.std_ns.class_('vector< std::shared_ptr<ompl::geometric::BITstar::Vertex> >').exclude()
        self.std_ns.class_('vector<const ompl::base::State *>').exclude()
        # exclude deprecated API function
        self.ompl_ns.free_function('getDefaultPlanner').exclude()

        # Using nullptr as a default value in method arguments causes
        # problems with Boost.Python.
        # See https://github.com/boostorg/python/issues/60
        self.ompl_ns.class_('PathSimplifier').add_declaration_code('#define nullptr NULL\n')

        # Py++ seems to get confused by some methods declared in one module
        # that are *not* overridden in a derived class in another module. The
        # Planner class is defined in ompl::base and two of its virtual methods,
        # setProblemDefinition and checkValidity, and not overridden by most
        # planners. The code below forces Py++ to do the right thing (or at
        # least make it work). It seems rather hacky and there may be a better
        # solution.
        planners = [p.related_class for p in self.ompl_ns.class_('Planner').recursive_derived]
        for planner in planners:
            planner.add_registration_code(
                'def("solve", (::ompl::base::PlannerStatus(::ompl::base::Planner::*)( double ))' \
                '(&::ompl::base::Planner::solve), (bp::arg("solveTime")) )')
            if planner.name != 'PRM':
                # PRM overrides setProblemDefinition, so we don't need to add this code
                planner.add_registration_code("""
                def("setProblemDefinition",&::ompl::base::Planner::setProblemDefinition,
                    &%s_wrapper::default_setProblemDefinition, (bp::arg("pdef")) )""" %
                                              planner.name)
            planner.add_registration_code("""
            def("checkValidity",&::ompl::base::Planner::checkValidity,
                &%s_wrapper::default_checkValidity )""" % planner.name)

        # The OMPL implementation of PRM uses two threads: one for constructing
        # the roadmap and another for checking for a solution. This causes
        # problems when both threads try to access the python interpreter
        # simultaneously. This is a known limitation of Boost.Python. We
        # therefore use a single-threaded version of PRM in python.
        PRM_cls = self.ompl_ns.class_('PRM')
        PRM_cls.member_function('solve').exclude()
        PRM_cls.add_wrapper_code("""
            virtual ::ompl::base::PlannerStatus solve(
                ::ompl::base::PlannerTerminationCondition const & ptc ) {
                if( bp::override func_solve = this->get_override( "solve" ) )
                    return func_solve( boost::ref(ptc) );
                else{
                    return default_solve( boost::ref(ptc) );
                }
            }

            ::ompl::base::PlannerStatus default_solve(
                ::ompl::base::PlannerTerminationCondition const & ptc );
            """)
        PRM_cls.add_declaration_code(open(join(dirname(__file__), \
            'PRM.SingleThreadSolve.cpp'), 'r').read())
        # This needs to be the last registration code added to the PRM_cls to the ugly hack below.
        PRM_cls.add_registration_code("""def("solve",
            (::ompl::base::PlannerStatus(::ompl::geometric::PRM::*)(
                ::ompl::base::PlannerTerminationCondition const &))(&PRM_wrapper::solve),
            (::ompl::base::PlannerStatus(PRM_wrapper::*)(
                ::ompl::base::PlannerTerminationCondition const & ))(&PRM_wrapper::default_solve), bp::arg("ptc") );

            // HACK ALERT: closing brace destroys bp::scope,
            // so that PRMstar is not a nested class of PRM
            }
            {
                // wrapper for PRMstar, derived from single-threaded PRM_wrapper
                bp::class_<PRMstar_wrapper, bp::bases< PRM_wrapper >, boost::noncopyable >("PRMstar", bp::init< ompl::base::SpaceInformationPtr const & >( bp::arg("si") ) )
            """)
        # Add wrapper code for PRM*
        PRM_cls.add_declaration_code("""
        class PRMstar_wrapper : public PRM_wrapper
        {
        public:
            PRMstar_wrapper(const ompl::base::SpaceInformationPtr &si) : PRM_wrapper(si, true)
            {
                setName("PRMstar");
                params_.remove("max_nearest_neighbors");
            }
        };
        """)
        # LazyPRM's Vertex type is void* so exclude addMilestone which has return type void*
        self.ompl_ns.class_('LazyPRM').member_function('addMilestone').exclude()
        # avoid difficulties in exporting the return type std::vector<base::PlannerDataPtr>
                # do this for all multithreaded planners
        for planner in ['SPARS', 'SPARStwo']:
            cls = self.ompl_ns.class_(planner)
            cls.constructor(arg_types=["::ompl::base::SpaceInformationPtr const &"]).exclude()
            cls.add_registration_code(
                'def(bp::init<ompl::base::SpaceInformationPtr const &>(bp::arg("si")))')
            cls.add_wrapper_code("""
            {0}_wrapper(::ompl::base::SpaceInformationPtr const &si) : ompl::geometric::{0}(si),
                bp::wrapper<ompl::geometric::{0}>()
            {{
                OMPL_WARN("%s: this planner uses multiple threads and might crash if your StateValidityChecker, OptimizationObjective, etc., are allocated within Python.", getName().c_str());
            }}
            """.format(planner))

        # exclude methods that use problematic types
        cls = self.ompl_ns.class_('SPARS')
        cls.member_function('addPathToSpanner').exclude()
        cls.member_function('computeDensePath').exclude()
        self.ompl_ns.class_('SPARStwo').member_function('findCloseRepresentatives').exclude()

        # needed to able to set connection strategy for PRM
        # the PRM::Vertex type is typedef-ed to boost::graph_traits<Graph>::vertex_descriptor. This
        # can be equal to an unsigned long or unsigned int, depending on architecture (or version
        # of boost?)
        try:
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned long>').rename('NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned long>').rename(
                'NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned long>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned long>').rename('KStarStrategy')
        except declaration_not_found_t:
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').include()
            self.ompl_ns.class_('NearestNeighbors<unsigned int>').rename('NearestNeighbors')
            self.ompl_ns.class_('NearestNeighborsLinear<unsigned int>').rename(
                'NearestNeighborsLinear')
            self.ompl_ns.class_('KStrategy<unsigned int>').rename('KStrategy')
            self.ompl_ns.class_('KStarStrategy<unsigned int>').rename('KStarStrategy')

        try:
            # Exclude some functions from BIT* that cause some Py++ compilation problems
            # (#I don't know why this doesn't work):
            self.ompl_ns.class_('BITstar').member_functions('getEdgeQueue').exclude()
            self.ompl_ns.class_('BITstar').member_functions('getVertexQueue').exclude()
        except declaration_not_found_t:
            pass
Esempio n. 56
0
    def get_header_info(self):
        """
        PyGCCXML header code parser
        magic happens here!
        : returns the parsed header data in python dict
        : return dict keys: namespace, class, io_signature, make,
                       properties, methods
        : Can be used as an CLI command or an extenal API
        """
        gr = self.modname.split('-')[0]
        module = self.modname.split('-')[-1]
        generator_path, generator_name = utils.find_xml_generator()
        xml_generator_config = parser.xml_generator_configuration_t(
            xml_generator_path=generator_path,
            xml_generator=generator_name,
            compiler='gcc')
        decls = parser.parse(
            [self.target_file], xml_generator_config)
        global_namespace = declarations.get_global_namespace(decls)

        # namespace
        try:
            self.parsed_data['namespace'] = []
            ns = global_namespace.namespace(gr)
            if ns is None:
                raise BlockToolException
            main_namespace = ns.namespace(module)
            if main_namespace is None:
                raise BlockToolException('namespace cannot be none')
            self.parsed_data['namespace'] = [gr, module]
            if main_namespace.declarations:
                for _namespace in main_namespace.declarations:
                    if isinstance(_namespace, declarations.namespace_t):
                        if Constants.KERNEL not in str(_namespace):
                            main_namespace = _namespace
                            self.parsed_data['namespace'].append(
                                str(_namespace).split('::')[-1].split(' ')[0])
        except RuntimeError:
            raise BlockToolException(
                'Invalid namespace format in the block header file')

        # class
        try:
            self.parsed_data['class'] = ''
            for _class in main_namespace.declarations:
                if isinstance(_class, declarations.class_t):
                    main_class = _class
                    self.parsed_data['class'] = str(_class).split('::')[
                        2].split(' ')[0]
        except RuntimeError:
            raise BlockToolException(
                'Block header namespace {} must consist of a valid class instance'.format(module))

        # io_signature, message_ports
        self.parsed_data['io_signature'] = {}
        self.parsed_data['message_port'] = {}
        if os.path.isfile(self.impl_file) and exist_comments(self):
            self.parsed_data['io_signature'] = io_signature(
                self.impl_file)
            self.parsed_data['message_port'] = message_port(
                self.impl_file)
            read_comments(self)
        elif os.path.isfile(self.impl_file) and not exist_comments(self):
            self.parsed_data['io_signature'] = io_signature(
                self.impl_file)
            self.parsed_data['message_port'] = message_port(
                self.impl_file)
            if self.addcomments:
                add_comments(self)
        elif not os.path.isfile(self.impl_file) and exist_comments(self):
            read_comments(self)
        else:
            self.parsed_data['io_signature'] = {
                "input": [],
                "output": []
            }
            self.parsed_data['message_port'] = self.parsed_data['io_signature']

        # make
        try:
            self.parsed_data['make'] = {}
            self.parsed_data['make']['arguments'] = []
            query_m = declarations.custom_matcher_t(
                lambda mem_fun: mem_fun.name.startswith('make'))
            query_make = query_m & declarations.access_type_matcher_t('public')
            make_func = main_class.member_functions(function=query_make,
                                                    allow_empty=True,
                                                    header_file=self.target_file)
            criteria = declarations.calldef_matcher(name='make')
            _make_fun = declarations.matcher.get_single(criteria, main_class)
            _make_fun = str(_make_fun).split(
                'make')[-1].split(')')[0].split('(')[1].lstrip().rstrip().split(',')
            if make_func:
                for arg in make_func[0].arguments:
                    for _arg in _make_fun:
                        if str(arg.name) in _arg:
                            make_arguments = {
                                "name": str(arg.name),
                                "dtype": str(arg.decl_type),
                                "default": ""
                            }
                            if re.findall(r'[-+]?\d*\.\d+|\d+', _arg):
                                make_arguments['default'] = re.findall(
                                    r'[-+]?\d*\.\d+|\d+', _arg)[0]
                            elif re.findall(r'\"(.+?)\"', _arg):
                                make_arguments['default'] = re.findall(
                                    r'\"(.+?)\"', _arg)[0]
                            elif "true" in _arg:
                                make_arguments['default'] = "True"
                            elif "false" in _arg:
                                make_arguments['default'] = "False"
                    self.parsed_data['make']['arguments'].append(
                        make_arguments.copy())
        except RuntimeError:
            self.parsed_data['make'] = {}
            self.parsed_data['make']['arguments'] = []

        # setters
        try:
            self.parsed_data['methods'] = []
            query_methods = declarations.access_type_matcher_t('public')
            setters = main_class.member_functions(function=query_methods,
                                                  allow_empty=True,
                                                  header_file=self.target_file)
            getter_arguments = []
            if setters:
                for setter in setters:
                    if str(setter.name).startswith('set_') and setter.arguments:
                        setter_args = {
                            "name": str(setter.name),
                            "arguments_type": []
                        }
                        for argument in setter.arguments:
                            args = {
                                "name": str(argument.name),
                                "dtype": str(argument.decl_type)
                            }
                            getter_arguments.append(args['name'])
                            setter_args['arguments_type'].append(args.copy())
                        self.parsed_data['methods'].append(setter_args.copy())
        except RuntimeError:
            self.parsed_data['methods'] = []

        # getters
        try:
            self.parsed_data['properties'] = []
            query_properties = declarations.access_type_matcher_t('public')
            getters = main_class.member_functions(function=query_properties,
                                                  allow_empty=True,
                                                  header_file=self.target_file)
            if getters:
                for getter in getters:
                    if not getter.arguments or getter.has_const:
                        getter_args = {
                            "name": str(getter.name),
                            "dtype": str(getter.return_type),
                            "read_only": True
                        }
                        if getter_args['name'] in getter_arguments:
                            getter_args["read_only"] = False
                        self.parsed_data['properties'].append(
                            getter_args.copy())
        except RuntimeError:
            self.parsed_data['properties'] = []

        # documentation
        try:
            _index = None
            header_file = codecs.open(self.target_file, 'r', 'cp932')
            self.parsed_data['docstring'] = re.compile(
                r'//.*?$|/\*.*?\*/', re.DOTALL | re.MULTILINE).findall(
                    header_file.read())[2:]
            header_file.close()
            for doc in self.parsed_data['docstring']:
                if Constants.BLOCKTOOL in doc:
                    _index = self.parsed_data['docstring'].index(doc)
            if _index is not None:
                self.parsed_data['docstring'] = self.parsed_data['docstring'][: _index]
        except:
            self.parsed_data['docstring'] = []

        return self.parsed_data
Esempio n. 57
0
    def redefined_funcs( self ):
        """
        returns list of member functions that should be defined in the class wrapper

        It comes useful in 3 tier hierarchy:

        .. code-block:: c++

           struct base{
               virtual void do_nothing() = 0;
           };

           struct derived{
               virtual void do_something() = 0;
           };

           struct concrete{
               virtual void do_nothing(){}
               virtual void do_something(){}
           };

        The wrapper for class `derived`, should define `do_nothing` function,
        otherwise the generated code will not compile
        """

        if isinstance( self._redefined_funcs, list ):
            return self._redefined_funcs

        all_included = declarations.custom_matcher_t( lambda decl: decl.ignore == False and decl.exportable )
        all_protected = declarations.access_type_matcher_t( 'protected' ) & all_included
        all_pure_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.PURE_VIRTUAL )
        all_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.VIRTUAL ) \
                      & ( declarations.access_type_matcher_t( 'public' ) \
                          | declarations.access_type_matcher_t( 'protected' ))
        all_not_pure_virtual = ~all_pure_virtual

        query = all_protected | all_pure_virtual
        mf_query = query | all_virtual
        relevant_opers = declarations.custom_matcher_t( lambda decl: decl.symbol in ('()', '[]') )
        funcs = []
        defined_funcs = []

        for base in self.recursive_bases:
            if base.access == ACCESS_TYPES.PRIVATE:
                continue
            base_cls = base.related_class

            funcs.extend( base_cls.member_functions( mf_query, recursive=False, allow_empty=True ) )
            funcs.extend( base_cls.member_operators( relevant_opers & query, recursive=False, allow_empty=True ) )

            defined_funcs.extend( base_cls.member_functions( all_not_pure_virtual, recursive=False, allow_empty=True ) )
            defined_funcs.extend( base_cls.member_operators( all_not_pure_virtual & relevant_opers, recursive=False, allow_empty=True ) )

        not_reimplemented_funcs = set()
        is_same_function = declarations.is_same_function
        for f in funcs:
            cls_fs = self.calldefs( name=f.name, recursive=False, allow_empty=True )
            for cls_f in cls_fs:
                if is_same_function( f, cls_f ):
                    break
            else:
                #should test whether this function has been added or not
                for f_impl in not_reimplemented_funcs:
                    if is_same_function( f, f_impl ):
                        if declarations.is_base_and_derived( f_impl.parent, f.parent ):
                            #add function from the most derived class
                            not_reimplemented_funcs.remove( f_impl )
                            not_reimplemented_funcs.add( f )
                        break
                else:
                    #should test whether this function is implemented in base class
                    if f.virtuality != VIRTUALITY_TYPES.PURE_VIRTUAL:
                        not_reimplemented_funcs.add( f )
                    else:
                        for f_defined in defined_funcs:
                            if is_same_function( f, f_defined ):
                                break
                        else:
                            not_reimplemented_funcs.add( f )
        functions = [f for f in list( not_reimplemented_funcs ) if ( False == f.ignore and True == f.exportable )
                                      or all_pure_virtual( f )]


        #Boost.Python is not able to call for non-virtual function, from the base
        #class if there is a virtual function with the same within base class
        #See override_bug tester for more information

        def buggy_bpl_filter( f ):
            if f.parent is self:
                return False
            if f.access_type != ACCESS_TYPES.PUBLIC:
                return False
            if f.virtuality != VIRTUALITY_TYPES.NOT_VIRTUAL:
                return False
            #we need to check that we don't have "same" function in this class
            this_funs = self.decls( name=f.name
                                    , decl_type=declarations.calldef_t
                                    , recursive=False
                                    , allow_empty=True )
            for this_f in this_funs:
                if is_same_function( this_f, f ):
                    #there is already the function in the class, so no need to redefined it
                    return False
            else:
                return True

        tmp = {} # id : f
        for redefined_f in functions:
            #redefined is virtual, I am not interested in virtual functions
            for rfo in redefined_f.overloads:
                if id(rfo) in tmp:
                    continue
                if buggy_bpl_filter( rfo ):
                    tmp[ id(rfo) ] = rfo
        functions.extend( list(tmp.values()) )

        functions.sort( key=lambda f: ( f.name, f.location.as_tuple() ) )

        self._redefined_funcs = functions
        return self._redefined_funcs
Esempio n. 58
0
    def filter_declarations(self, mb):
        mb.global_ns.exclude()
        mb.global_ns.namespace("pyplusplus", recursive=False).include()
        boost_ns = mb.global_ns.namespace("boost", recursive=False)
        boost_ns.namespace("posix_time", recursive=False).include()
        boost_ns.namespace("date_time", recursive=False).include()
        boost_ns.namespace("gregorian", recursive=False).include()
        boost_ns.namespace("local_time", recursive=False).include()
        boost_ns.classes(lambda decl: decl.name.startswith("constrained_value<")).include()
        ## Exclude protected and private that are not pure virtual
        query = ~declarations.access_type_matcher_t("public") & ~declarations.virtuality_type_matcher_t(
            declarations.VIRTUALITY_TYPES.PURE_VIRTUAL
        )
        non_public_non_pure_virtual = boost_ns.calldefs(query)
        non_public_non_pure_virtual.exclude()

        for name in ["month_str_to_ushort", "from_stream_type", "parse_date"]:
            boost_ns.calldefs(lambda decl: decl.name.startswith(name)).exclude()

        to_be_removed = [
            "c_time",
            "duration_traits_long",
            "duration_traits_adapted",
            "posix_time_system_config",  # TODO find out link bug
            "millisec_posix_time_system_config",
        ]
        boost_ns.classes(lambda decl: decl.name in to_be_removed).exclude()

        starts_with = [
            "time_resolution_traits<",
            "counted_time_rep<",
            "date_facet<",
            "period_formatter<",
            "date_generator_formatter<",
            "special_values_formatter<",
        ]
        for name in starts_with:
            boost_ns.classes(lambda decl: decl.name.startswith(name)).exclude()

        ends_with = ["_impl", "_config"]
        for name in ends_with:
            boost_ns.classes(lambda decl: decl.name.endswith(name)).exclude()

        boost_ns.classes(lambda decl: decl.alias.endswith("formatter")).exclude()

        # boost.date_time has problem to create local_[micro]sec_clock
        # variable, it has nothing to do with Py++
        empty_classes = ["local_microsec_clock", "local_sec_clock"]
        for alias in empty_classes:
            class_ = boost_ns.class_(lambda decl: decl.alias == alias)
            class_.exclude()
            class_.ignore = False

        for alias in ["microsec_clock", "second_clock"]:
            class_ = boost_ns.class_(lambda decl: decl.alias == alias)
            class_.calldefs().create_with_signature = True

        tdi = mb.class_(lambda decl: decl.alias == "time_duration_impl")
        tdi_init = tdi.constructor(arg_types=[None, None, None, None], recursive=False)
        tdi_init.ignore = True
        # next declarations are not exported, but Py++ writes warnings about them:
        boost_ns.operators("<<").exclude()
        boost_ns.operators(">>").exclude()
        boost_ns.operators("=").exclude()
        # next function uses non public class in its definition.
        microsec_clocks = boost_ns.classes(lambda decl: decl.name.startswith("microsec_clock<"))
        for mc in microsec_clocks:
            mc.member_functions("create_time").exclude()

        # TODO: add FT
        # next function takes reference to int. This function could not be called
        # from Python. Function transformation feature solves this problem
        tz_db_base = boost_ns.class_(lambda decl: decl.name.startswith("tz_db_base<"))
        tz_db_base.member_functions("split_rule_spec").exclude()