def _generate_constructor(self): result = [] result.append( '(' ) result.append( ' "%s"' % self.alias ) if self.documentation: result.append( ', %s' % self.documentation ) used_init = None inits = filter( lambda x: isinstance( x, calldef.constructor_t ), self.creators ) if ( self.declaration.is_abstract \ or not declarations.has_any_non_copyconstructor(self.declaration) ) \ and not self.wrapper \ or ( declarations.has_destructor( self.declaration ) and not declarations.has_public_destructor( self.declaration ) ): #TODO: or self.declaration has public constructor and destructor result.append( ", " ) result.append( algorithm.create_identifier( self, '::boost::python::no_init' ) ) elif not declarations.has_trivial_constructor( self.declaration ): if inits: used_init = inits[0] result.append( ", " ) result.append( used_init.create_init_code() ) elif self.declaration.indexing_suite: pass #in this case all constructors are exposed by indexing suite else:#it is possible to class to have public accessed constructor #that could not be exported by boost.python library #for example constructor takes as argument pointer to function result.append( ", " ) result.append( algorithm.create_identifier( self, '::boost::python::no_init' ) ) else: pass result.append( ' )' ) return ( ''.join( result ), used_init )
def _get_no_init( self ): if None is self._no_init and False == bool( self.indexing_suite ): #select all public constructors and exclude copy constructor cs = self.constructors( lambda c: not c.is_copy_constructor and c.access_type == 'public' , recursive=False, allow_empty=True ) has_suitable_constructor = bool( cs ) if cs and len(cs) == 1 and cs[0].is_trivial_constructor and self.find_noncopyable_vars(): has_suitable_constructor = False has_nonpublic_destructor = declarations.has_destructor( self ) \ and not declarations.has_public_destructor( self ) trivial_constructor = self.find_trivial_constructor() if has_nonpublic_destructor \ or ( self.is_abstract and not self.is_wrapper_needed() ) \ or not has_suitable_constructor: self._no_init = True elif not trivial_constructor or trivial_constructor.access_type != 'public': exportable_cs = [c for c in cs if c.exportable and c.ignore == False] if not exportable_cs: self._no_init = True else: pass if None is self._no_init: self._no_init = False return self._no_init
def _get_no_init(self): if None is self._no_init and False == bool(self.indexing_suite): #select all public constructors and exclude copy constructor cs = self.constructors(lambda c: not c.is_copy_constructor and c. access_type == 'public', recursive=False, allow_empty=True) has_suitable_constructor = bool(cs) if cs and len(cs) == 1 and cs[ 0].is_trivial_constructor and self.find_noncopyable_vars(): has_suitable_constructor = False has_nonpublic_destructor = declarations.has_destructor( self ) \ and not declarations.has_public_destructor( self ) trivial_constructor = self.find_trivial_constructor() if has_nonpublic_destructor \ or ( self.is_abstract and not self.is_wrapper_needed() ) \ or not has_suitable_constructor: self._no_init = True elif not trivial_constructor or trivial_constructor.access_type != 'public': exportable_cs = filter( lambda c: c.exportable and c.ignore == False, cs) if not exportable_cs: self._no_init = True else: pass if None is self._no_init: self._no_init = False return self._no_init
def customize(self, mb): access_type_matcher = declarations.access_type_matcher_t mb.global_ns.include() mb.classes(access_type_matcher('protected')).exclude() mb.vars(access_type_matcher('protected')).exclude() mb.class_(lambda d: d.name.startswith('buffered_value')).exclude() for cls in mb.classes(): if declarations.has_destructor(cls) \ and cls.calldef(lambda d: d.name.startswith('~'), recursive=False).access_type == 'protected': print('protected destructor: ', str(cls)) cls.constructors().exclude() cls.noncopyable = True
def customize(self, mb ): access_type_matcher = declarations.access_type_matcher_t mb.global_ns.include() mb.classes( access_type_matcher('protected') ).exclude() mb.vars( access_type_matcher('protected') ).exclude() mb.class_( lambda d: d.name.startswith( 'buffered_value' ) ).exclude() for cls in mb.classes(): if declarations.has_destructor(cls) \ and cls.calldef(lambda d: d.name.startswith('~'), recursive=False).access_type == 'protected': print 'protected destructor: ', str( cls ) cls.constructors().exclude() cls.noncopyable = True
def __call__(self, variable, hint=None): if not isinstance(variable, declarations.variable_t): return None assert hint in ('get', 'set') if not declarations.is_reference(variable.decl_type): return None no_ref = declarations.remove_reference(variable.decl_type) base_type = declarations.remove_const(no_ref) if python_traits.is_immutable(base_type): #the relevant code creator will generate code, that will return this member variable #by value return decl_wrappers.default_call_policies() if not isinstance(base_type, declarations.declarated_t): return None base_type = declarations.remove_alias(base_type) declaration = base_type.declaration if declarations.is_class_declaration(declaration): return None if declaration.is_abstract: return None if declarations.has_destructor( declaration ) and not declarations.has_public_destructor(declaration): return None if not declarations.has_copy_constructor(declaration): return None if hint == 'get': #if we rich this line, it means that we are able to create an obect using #copy constructor. if declarations.is_const(no_ref): return decl_wrappers.return_value_policy( decl_wrappers.copy_const_reference) else: return decl_wrappers.return_value_policy( decl_wrappers.copy_non_const_reference) else: return decl_wrappers.default_call_policies()
def _get_has_setter( self ): if declarations.is_const( declarations.remove_reference( self.declaration.type ) ): return False elif python_traits.is_immutable( self._get_exported_var_type() ): return True else: pass no_ref = declarations.remove_reference( self.declaration.type ) no_const = declarations.remove_const( no_ref ) base_type = declarations.remove_alias( no_const ) if not isinstance( base_type, declarations.declarated_t ): return True #TODO ???? decl = base_type.declaration if decl.is_abstract: return False if declarations.has_destructor( decl ) and not declarations.has_public_destructor( decl ): return False if not declarations.has_copy_constructor(decl): return False return True
def __call__( self, variable, hint=None ): if not isinstance( variable, declarations.variable_t ): return None assert hint in ( 'get', 'set' ) if not declarations.is_reference( variable.type ): return None no_ref = declarations.remove_reference( variable.type ) base_type = declarations.remove_const( no_ref ) if python_traits.is_immutable( base_type ): #the relevant code creator will generate code, that will return this member variable #by value return decl_wrappers.default_call_policies() if not isinstance( base_type, declarations.declarated_t ): return None base_type = declarations.remove_alias( base_type ) decl = base_type.declaration if declarations.is_class_declaration( decl ): return None if decl.is_abstract: return None if declarations.has_destructor( decl ) and not declarations.has_public_destructor( decl ): return None if not declarations.has_copy_constructor(decl): return None if hint == 'get': #if we rich this line, it means that we are able to create an obect using #copy constructor. if declarations.is_const( no_ref ): return decl_wrappers.return_value_policy( decl_wrappers.copy_const_reference ) else: return decl_wrappers.return_value_policy( decl_wrappers.copy_non_const_reference ) else: return decl_wrappers.default_call_policies()
def _generate_constructor(self): result = [] result.append('(') result.append(' "%s"' % self.alias) if self.documentation: result.append(', %s' % self.documentation) used_init = None inits = filter(lambda x: isinstance(x, calldef.constructor_t), self.creators) if ( self.declaration.is_abstract \ or not declarations.has_any_non_copyconstructor(self.declaration) ) \ and not self.wrapper \ or ( declarations.has_destructor( self.declaration ) and not declarations.has_public_destructor( self.declaration ) ): #TODO: or self.declaration has public constructor and destructor result.append(", ") result.append( algorithm.create_identifier(self, '::boost::python::no_init')) elif not declarations.has_trivial_constructor(self.declaration): if inits: used_init = inits[0] result.append(", ") result.append(used_init.create_init_code()) elif self.declaration.indexing_suite: pass #in this case all constructors are exposed by indexing suite else: #it is possible to class to have public accessed constructor #that could not be exported by boost.python library #for example constructor takes as argument pointer to function result.append(", ") result.append( algorithm.create_identifier(self, '::boost::python::no_init')) else: pass result.append(' )') return (''.join(result), used_init)
def Auto_Functional_Transformation ( mb, ignore_funs=[], special_vars=[]): toprocess = [] aliases={} for fun in mb.member_functions(allow_empty=True): toprocess.append( fun ) for fun in mb.free_functions(allow_empty=True): toprocess.append( fun ) for fun in toprocess: fun_demangled = fun.demangled # need to check as extern functions don't have demangled name... if fun_demangled: # try: # ugly wrapping in a try :( fullname = fun.demangled.split('(')[0] if fullname not in ignore_funs and not fun.ignore: outputonly = False arg_position = 0 trans=[] desc="" ft_type = None ctypes_conversion = False for arg in fun.arguments: rawarg = declarations.remove_declarated( declarations.remove_const( declarations.remove_reference( declarations.remove_pointer ( arg.type )))) ## now check if the arg is a fundemental type (int float etc), a void ## or a special .. if declarations.is_arithmetic (rawarg)\ or declarations.is_void(rawarg)\ or arg.type.decl_string in special_vars: if declarations.is_pointer(arg.type): #we convert any pointers to unsigned int's # now look to see if it's a char * and if so we treat it as a string.. # # print "**" , declarations.remove_alias( rawarg ), declarations.type_traits.create_cv_types( declarations.cpptypes.char_t()) if declarations.remove_alias( rawarg ) in declarations.type_traits.create_cv_types( declarations.cpptypes.char_t() ): print ("MATCHED CString", fun) trans.append( ft.input_c_string(arg_position, 4096 ) ) desc = desc +"Argument: "+arg.name+ "( pos:" + str(arg_position) + " - " +\ arg.type.decl_string + " ) takes a python string. \\n" ctypes_conversion = True ctypes_arg = arg.type.decl_string.split()[0] ft_type = 'CTYPES' else: trans.append( ft.modify_type(arg_position,_ReturnUnsignedInt ) ) desc = desc +"Argument: "+arg.name+ "( pos:" + str(arg_position) + " - " +\ arg.type.decl_string + " ) takes a CTypes.addressof(xx). \\n" ctypes_conversion = True ctypes_arg = arg.type.decl_string.split()[0] ft_type = 'CTYPES' elif declarations.is_reference(arg.type)and not declarations.is_const(declarations.remove_reference( arg.type)): # seen functions passing const ref's trans.append( ft.inout(arg_position ) ) desc = desc + "Argument: "+arg.name+ "( pos:" + str(arg_position) + " - " +\ arg.type.decl_string + " ) converted to an input/output (change to return types).\\n" ft_type = 'INOUT' elif declarations.is_reference(arg.type): print ("Warning: - possible code change.", fun,arg," not wrapped as const reference to base type invalid") else: pass # it isn't a pointer or reference so doesn't need wrapping else: pass # it's not a var we need to handle arg_position += 1 if trans: const_return = False # declarations.is_const(fun) if fun.decl_string.endswith('const'): const_return=True simple_return = declarations.is_arithmetic(fun.return_type) or declarations.is_void(fun.return_type) nonpublic_destructor = declarations.is_class(fun.parent) and declarations.has_destructor(fun.parent) and\ not declarations.has_public_destructor(fun.parent) if fun.documentation or fun.transformations: # it's already be tweaked: print ("AUTOFT ERROR: Duplicate Tranforms.", fun, fun.documentation) # if the class has a protected destruction AND the return value is const or a non arithmatic value then exclude it. elif nonpublic_destructor and const_return: print ("AUTOFT ERROR Const: Parent has non public destructor and const return.", fun.parent.name, fun.return_type.decl_string, fun) fun.documentation="Python-Ogre Warning: function required transformation - not possible due to non public destructor and const return value.." elif nonpublic_destructor and not simple_return: print ("AUTOFT ERROR Const: Parent has non public destructor and complex return value.", fun.parent.name, fun.return_type.decl_string, fun) fun.documentation="Python-Ogre Warning: function required transformation - not possible due to non public destructor and complex return value.." else: new_alias = fun.name if ctypes_conversion: # only manage name changes if ctypes changing # now lets look for a duplicate function name with the same number arguments f= [None]*len(fun.arguments) s = mb.member_functions("::" + fullname, arg_types=f, allow_empty=True) if len (s) > 1: # there are duplicate names so need to create something unique ctypes_arg = ctypes_arg.replace("::", "_") # to clean up function names... new_alias = fun.name + ctypes_arg[0].upper() + ctypes_arg[1:] # now for REAL ugly code -- we have faked a new alias and it may not be unique # so we track previous alias + class name to ensure unique names are generated keyname = fullname + new_alias # we use the full class + function name + alias as the key if keyname in aliases: # already exists, need to fake another version.. new_alias = new_alias + "_" + str( aliases[keyname] ) aliases[keyname] = aliases[keyname] + 1 else: aliases[keyname] = 1 desc = desc + "\\\nWARNING FUNCTION NAME CHANGE - from "+fun.name + " -- " + fun.decl_string +" to " + new_alias + " \\n" print ("INFO: Adjusting Alias as multiple overlapping functions:", new_alias) print ("AUTOFT OK: Tranformed ", fun.return_type.decl_string, fun, "(",new_alias,")") fun.add_transformation ( * trans , **{"alias":new_alias} ) fun.documentation = docit ("Auto Modified Arguments:", desc, "...")