def fix_pointer_returns (classes, pointee_types = None, ignore_names = None): """ Change out functions that return a variety of pointer to base types and instead have them return the address the pointer is pointing to (the pointer value) This allow us to use CTypes to handle in memory buffers from Python Also - if documentation has been set then ignore the class/function as it means it's been tweaked else where """ if pointee_types is None: pointee_types = ['unsigned int', 'int', 'float', 'double', 'char', 'unsigned char'] if ignore_names is None: ignore_names = [] for cls in classes: for fun in cls.member_functions( allow_empty = True ): if declarations.is_pointer (fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith ( i ) and not fun.documentation: if not fun.name in ignore_names: decl_logger.info("Excluding (function): %s as it returns (pointer) %s" % (fun, i)) fun.exclude() for fun in cls.member_operators( allow_empty = True ): if declarations.is_pointer (fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith ( i ) and not fun.documentation: decl_logger.info("Excluding (operator): %s" % fun) fun.exclude()
def call_traits(type_): """http://boost.org/libs/utility/call_traits.htm""" type_ = declarations.remove_alias(type_) if is_immutable(type_): return "%(arg)s" #pass by value elif declarations.is_reference(type_): no_ref = declarations.remove_reference(type_) if is_immutable(no_ref): return "%(arg)s" #pass by value else: return "boost::ref(%(arg)s)" #pass by ref elif declarations.is_pointer( type_ ) \ and not is_immutable( type_.base ) \ and not declarations.is_pointer( type_.base ): base = type_.base while hasattr(base, 'base'): base = base.base if hasattr(base.declaration, 'custom_call_trait'): custom_call_trait = base.declaration.custom_call_trait call_trait = custom_call_trait( type_) if custom_call_trait else None if call_trait: return call_trait return "boost::python::ptr(%(arg)s)" #pass by ptr else: return "%(arg)s" #pass by value
def Fix_Pointer_Returns ( mb ): """ Change out functions that return a variety of pointers to base types and instead have them return the address the pointer is pointing to (the pointer value) This allow us to use CTypes to handle in memory buffers from Python Also - if documentation has been set then ignore the class/function as it means it's been tweaked else where """ pointee_types=['unsigned int','int', 'float', 'unsigned char', '::udword', '::sbyte' ] known_names=[] # these are function names we know it's cool to exclude for fun in mb.member_functions(): if declarations.is_pointer (fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith ( i ) and not fun.documentation: if not fun.name in known_names: print "Excluding (function):", fun, "as it returns (pointer)", i fun.exclude() try: for fun in mb.member_operators(): if declarations.is_pointer (fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith ( i ) and not fun.documentation: print "Excluding (operator):", fun fun.exclude() except: pass
def filter_decls(mb): mb.global_ns.exclude() fx_ns = mb.namespace( 'FX' ) fx_ns.include() fx_ns.decls( declarations_to_exclude.is_excluded ).exclude() fx_ns.decls( lambda decl: decl.name.startswith('FXIPCMsgHolder') ).exclude() fx_ns.namespace( 'Pol' ).exclude() fx_ns.decls( files_to_exclude.is_excluded ).exclude() fx_ns.class_( 'QValueList<FX::Pol::knowReferrers::ReferrerEntry>').exclude() try: fx_ns.variables( 'metaClass').exclude() except: pass try: fx_ns.class_( 'QPtrVector<FX::Generic::BoundFunctorV>').exclude() except: pass #Niall? wrapper for this function could not be compiled #TnFXSQLDBStatement = fx_ns.class_( 'TnFXSQLDBStatement' ) #TnFXSQLDBStatement.member_function( name='bind', arg_types=[None,None,None] ).exclude() for func in fx_ns.calldefs(): #I want to exclude all functions that returns pointer to pointer #and returns pointer to fundamental type if declarations.is_pointer( func.return_type ): temp = declarations.remove_pointer( func.return_type ) if declarations.is_fundamental( temp ) and not declarations.is_const(temp): func.exclude() temp = declarations.remove_cv( func.return_type ) temp = declarations.remove_pointer( temp ) if declarations.is_pointer( temp ): func.exclude()
def call_traits( type_ ): """http://boost.org/libs/utility/call_traits.htm""" type_ = declarations.remove_alias( type_ ) if is_immutable( type_ ): return "%(arg)s" #pass by value elif declarations.is_reference( type_ ): no_ref = declarations.remove_reference( type_ ) if is_immutable( no_ref ): return "%(arg)s" #pass by value else: return "boost::ref(%(arg)s)" #pass by ref elif declarations.is_pointer( type_ ) \ and not is_immutable( type_.base ) \ and not declarations.is_pointer( type_.base ): base = type_.base while hasattr(base, 'base'): base = base.base if hasattr(base.declaration, 'custom_call_trait'): custom_call_trait = base.declaration.custom_call_trait call_trait = custom_call_trait(type_) if custom_call_trait else None if call_trait: return call_trait return "boost::python::ptr(%(arg)s)" #pass by ptr else: return "%(arg)s" #pass by value
def __find_out_class_dependencies(self, class_): full_name = declarations.full_name #class depends on it's base classes i_depend_on_them = set( [full_name(base.related_class) for base in class_.bases]) #class depends on all classes that used in function as argument # types and those arguments have default value calldefs = [ decl for decl in declarations.make_flatten(class_) if isinstance(decl, declarations.calldef_t) ] for calldef in calldefs: for arg in calldef.arguments: if declarations.is_enum(arg.type): top_class_inst = self.__get_top_class_inst( declarations.enum_declaration(arg.type)) if top_class_inst: i_depend_on_them.add(full_name(top_class_inst)) continue if not arg.default_value: continue if declarations.is_pointer( arg.type) and arg.default_value == 0: continue base_type = declarations.base_type(arg.type) if not isinstance(base_type, declarations.declarated_t): continue top_class_inst = self.__get_top_class_inst( base_type.declaration) if top_class_inst: i_depend_on_them.add(full_name(top_class_inst)) if self.__include_vars: vars = [ decl for decl in declarations.make_flatten(class_) if isinstance(decl, declarations.variable_t) ] for var in vars: if declarations.is_pointer(var.type): continue base_type = declarations.base_type(var.type) if not isinstance(base_type, declarations.declarated_t): continue top_class_inst = self.__get_top_class_inst( base_type.declaration) if top_class_inst: i_depend_on_them.add(full_name(top_class_inst)) for internal_cls in class_.classes(allow_empty=True): internal_cls_dependencies = self.__find_out_class_dependencies( internal_cls) i_depend_on_them.update(internal_cls_dependencies) i_depend_on_them = list(i_depend_on_them) i_depend_on_them.sort() return i_depend_on_them
def Fix_Void_Ptr_Args ( mb ): """ we modify functions that take void *'s in their argument list to instead take unsigned ints, which allows us to use CTypes buffers """ for fun in mb.member_functions(): arg_position = 0 for arg in fun.arguments: if declarations.type_traits.is_void_pointer(arg.type) or arg.type.decl_string == "void const *": fun.add_transformation( ft.modify_type(arg_position,_ReturnUnsignedInt ), alias=fun.name ) fun.documentation = docit ("Modified Input Argument to work with CTypes", "Argument "+arg.name+ "(pos:" + str(arg_position)\ +") takes a CTypes.adddressof(xx)", "...") print "Fixed Void Ptr", fun, arg_position break arg_position +=1 ## lets go and look for stuff that might be a problem pointee_types=['unsigned int',' int ', ' float ', ' Real ', 'uchar', 'uint8', 'unsigned char'] function_names=[] for fun in mb.member_functions(): if fun.documentation or fun.ignore: continue ## means it's been tweaked somewhere else for n in function_names: if n in fun.name: print "CHECK :", fun break arg_position = 0 for arg in fun.arguments: if declarations.is_pointer(arg.type): ## and "const" not in arg.type.decl_string: for i in pointee_types: if i in arg.type.decl_string: print '"',arg.type.decl_string, '"' print "CHECK ", fun, str(arg_position) fun.documentation=docit("SUSPECT - MAYBE BROKEN", "....", "...") break arg_position +=1 ## NEED To do the same for constructors for fun in mb.constructors(): arg_position = 0 for arg in fun.arguments: if declarations.is_pointer(arg.type): ## and "const" not in arg.type.decl_string: for i in pointee_types: if i in arg.type.decl_string: print '"',arg.type.decl_string, '"' print "Excluding: ", fun fun.exclude() break arg_position +=1
def Fix_Pointer_Returns ( mb, pointee_types=['unsigned int','int', 'float','char','unsigned char', 'bool', '::Ogre::uint8', '::Ogre::uint16', '::Ogre::uint32' ], known_names=[]): """ Change out functions that return a variety of pointer to base types and instead have them return the address the pointer is pointing to (the pointer value) This allow us to use CTypes to handle in memory buffers from Python Also - if documentation has been set then ignore the class/function as it means it's been tweaked else where """ for fun in mb.member_functions( allow_empty = True ): if declarations.is_pointer (fun.return_type) and not fun.documentation: # print "Checking", fun, fun.return_type.decl_string for i in pointee_types: if fun.return_type.decl_string.startswith ( i ) and not fun.documentation: if not fun.name in known_names: print ("WARNING: Func (", fun.name, ") returns ", i, ".Using ctype return_addressof functionality") fun.call_policies = call_policies.return_value_policy( call_policies.return_addressof ) fun.documentation=docit("CTYPE Integration - returns address of return value", "...", "Address of Return Value") # print "WARNING: Excluding (function):", fun, "as it returns (pointer)", i # fun.exclude() for fun in mb.member_operators( allow_empty = True ): if declarations.is_pointer (fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith ( i ) and not fun.documentation: print ("WARNING: Excluding (operator):", fun) fun.exclude() # Change 15 Feb 2008 -- adding free function management for fun in mb.free_functions( allow_empty = True ): if declarations.is_pointer (fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith ( i ) and not fun.documentation: if not fun.name in known_names: print ("WARNING: Excluding (free function):", fun, "as it returns (pointer)", i) fun.exclude() # Update 30 July 2008 -- support for void * variables to be exposed with ctypes handling for v in mb.variables( allow_empty=True ): supported = ['void const *','void *', 'char const *','char *', 'unsigned char const *','unsigned char *' ] if v.type.decl_string in supported: try: # this only works on memeber vars not global ones so need to check if v.access_type == 'public' and not v.documentation: # if not v.parent.noncopyable: ## this test as we don't support classes with protected destructors print ("CTYPE Implementation on ", v, v.access_type) v.expose_address = True except : #RunTimeError: pass
def _exportable_impl(self): if not self.name: return messages.W1033 if self.bits == 0 and self.name == "": return messages.W1034 if declarations.is_array( self.type) and declarations.array_size(self.type) < 1: return messages.W1045 type_ = declarations.remove_alias(self.type) type_ = declarations.remove_const(type_) if declarations.is_pointer(type_): if self.type_qualifiers.has_static: return messages.W1035 if python_traits.is_immutable(type_.base): return messages.W1036 units = declarations.decompose_type(type_) ptr2functions = filter( lambda unit: isinstance(unit, declarations.calldef_type_t), units) if ptr2functions: return messages.W1037 type_ = declarations.remove_pointer(type_) if declarations.class_traits.is_my_case(type_): cls = declarations.class_traits.get_declaration(type_) if not cls.name: return messages.W1038 if isinstance(self.parent, declarations.class_t): if self.access_type != declarations.ACCESS_TYPES.PUBLIC: return messages.W1039 return ''
def fix_ptr_fun(fun, pointee_types = None, ignore_names = None, Exclude = False): """ Allows to exclude or mark with a warning functions which take pointers as arguments It ignores already documented functions, because those have been fixed elsewhere """ if pointee_types is None: pointee_types = [] if ignore_names is None: ignore_names = [] if fun.documentation or fun.ignore: # means it's been tweaked somewhere else return for n in ignore_names: if n in fun.name: return for arg in fun.arguments: # and "const" not in arg.type.decl_string: if declarations.is_pointer(arg.type): for i in pointee_types: if arg.type.decl_string.startswith(i): if Exclude: decl_logger.info("Excluding: %s due to pointer argument %s" % (fun, arg.type.decl_string)) fun.exclude() return else: decl_logger.info("Function has pointer argument: %s %s" % (fun, arg.type.decl_string)) fun.documentation=docit("SUSPECT - MAYBE BROKEN due to pointer argument", "....", "...") return
def keywords_args(self): if not self.__args: return '' boost_arg = self.__id_creator('::boost::python::arg') boost_obj = self.__id_creator('::boost::python::object') result = ['( '] for arg in self.__args: if 1 < len(result): result.append(self.PARAM_SEPARATOR) result.append(boost_arg) result.append('("%s")' % arg.name) if self.__decl.use_default_arguments and arg.default_value: if not declarations.is_pointer( arg.type) or arg.default_value != '0': arg_type_no_alias = declarations.remove_alias(arg.type) if declarations.is_fundamental( arg_type_no_alias ) \ and declarations.is_integral( arg_type_no_alias ) \ and not arg.default_value.startswith( arg_type_no_alias.decl_string ): result.append( '=(%s)(%s)' % (arg.type.partial_decl_string, arg.default_value)) elif self.__should_use_enum_wa(arg): #Work around for bug/missing functionality in boost.python. #registration order result.append('=(long)(%s)' % arg.default_value) else: result.append('=%s' % arg.default_value) else: result.append('=%s()' % boost_obj) result.append(' )') return ''.join(result)
def _create_impl(self): if declarations.is_pointer(self.declaration.type): return self._generate_for_pointer() elif self.declaration.apply_smart_ptr_wa or self.declaration.use_make_functions: return self._generate_using_functions() else: return self._generate_for_none_pointer()
def wrap_ImageWindow(self): self.mb.class_('ImageWindowReceiver').exclude() self.mb.class_('ImageWindowDispatcher').exclude() cls = self.mb.class_('ImageWindow') cls.include() cls.variables('handle').exclude() # get/set image fn1 = cls.member_function("getImage") fn1.call_policies = call_policies.return_internal_reference() fn2 = cls.member_function("setImage") fn2.call_policies = call_policies.with_custodian_and_ward(1,2) cls.add_property( 'image' , cls.member_function( 'getImage' ) , cls.member_function( 'setImage' ) ) # get/set name cls.add_property( 'name' , cls.member_function( 'getName' ) , cls.member_function( 'setName' ) ) # 3D window controls fn = cls.member_function("getView3DControl") fn.call_policies = call_policies.return_internal_reference() cls.add_property('view3DControl', fn) fn = cls.member_function("getLocalView3DControl") fn.call_policies = call_policies.return_internal_reference() cls.add_property('localView3DControl', fn) fn = cls.member_function("getTriviewControl") fn.call_policies = call_policies.return_internal_reference() cls.add_property('triViewControl', fn) # exclude constructor that takes void* argument for ctor in cls.constructors(arg_types = [None]): arg_t = ctor.argument_types[0] if (declarations.is_pointer(arg_t)): ctor.exclude()
def keywords_args(self): if not self.__args: return "" boost_arg = self.__id_creator("::boost::python::arg") boost_obj = self.__id_creator("::boost::python::object") result = ["( "] for arg in self.__args: if 1 < len(result): result.append(self.PARAM_SEPARATOR) result.append(boost_arg) result.append('("%s")' % arg.name) if self.__decl.use_default_arguments and arg.default_value: if not declarations.is_pointer(arg.type) or arg.default_value != "0": arg_type_no_alias = declarations.remove_alias(arg.type) if ( declarations.is_fundamental(arg_type_no_alias) and declarations.is_integral(arg_type_no_alias) and not arg.default_value.startswith(arg_type_no_alias.decl_string) ): result.append("=(%s)(%s)" % (arg_type_no_alias.partial_decl_string, arg.default_value)) elif self.__should_use_enum_wa(arg): # Work around for bug/missing functionality in boost.python. # registration order result.append("=(long)(%s)" % arg.default_value) else: result.append("=%s" % arg.default_value) else: result.append("=%s()" % boost_obj) result.append(" )") return "".join(result)
def wrap_one_QList(self, cls): cls.include() cls.variables().exclude() # Avoid constructor that takes Node* argument for ctor in cls.constructors(arg_types=[None]): arg_t = ctor.argument_types[0] if (declarations.is_pointer(arg_t)): ctor.exclude() for fn_name in ['detach_helper_grow', 'node_construct', 'node_destruct', 'node_copy', 'fromVector', 'toVector', 'toSet', 'fromSet']: cls.member_functions(fn_name).exclude() for fn_name in ['back', 'first', 'front', 'last']: cls.member_functions(fn_name).call_policies = \ call_policies.return_internal_reference() # TODO - add python sequence operators cls.include_files.append("qlist_py_indexing.h") cls.add_registration_code(""" def(bp::indexing::container_suite< %s, bp::indexing::all_methods, list_algorithms<qlist_container_traits<%s > > >()) """ % (cls.demangled, cls.demangled) )
def remove_ref_or_ptr( type_ ): if declarations.is_pointer( type_ ): return declarations.remove_pointer( type_ ) elif declarations.is_reference( type_ ): return declarations.remove_reference( type_ ) else: raise TypeError( 'Type should be reference or pointer, got %s.' % type_ )
def _exportable_impl( self ): if not self.name: return messages.W1033 if self.bits == 0 and self.name == "": return messages.W1034 if declarations.is_array( self.type ) and declarations.array_size( self.type ) < 1: return messages.W1045 type_ = declarations.remove_alias( self.type ) type_ = declarations.remove_const( type_ ) if declarations.is_pointer( type_ ): if self.type_qualifiers.has_static: return messages.W1035 if python_traits.is_immutable( type_.base ): return messages.W1036 units = declarations.decompose_type( type_ ) ptr2functions = filter( lambda unit: isinstance( unit, declarations.calldef_type_t ) , units ) if ptr2functions: return messages.W1037 type_ = declarations.remove_pointer( type_ ) if declarations.class_traits.is_my_case( type_ ): cls = declarations.class_traits.get_declaration( type_ ) if not cls.name: return messages.W1038 if isinstance( self.parent, declarations.class_t ): if self.access_type != declarations.ACCESS_TYPES.PUBLIC: return messages.W1039 return ''
def __find_out_class_dependencies( self, class_ ): full_name = declarations.full_name #class depends on it's base classes i_depend_on_them = set( [ full_name( base.related_class ) for base in class_.bases ] ) #class depends on all classes that used in function as argument # types and those arguments have default value calldefs = filter( lambda decl: isinstance( decl, declarations.calldef_t ) , declarations.make_flatten( class_ )) for calldef in calldefs: for arg in calldef.arguments: if declarations.is_enum( arg.type ): top_class_inst = self.__get_top_class_inst( declarations.enum_declaration( arg.type ) ) if top_class_inst: i_depend_on_them.add( full_name( top_class_inst ) ) continue if not arg.default_value: continue if declarations.is_pointer( arg.type ) and arg.default_value == 0: continue base_type = declarations.base_type( arg.type ) if not isinstance( base_type, declarations.declarated_t ): continue top_class_inst = self.__get_top_class_inst( base_type.declaration ) if top_class_inst: i_depend_on_them.add( full_name( top_class_inst ) ) for internal_cls in class_.classes(allow_empty=True): internal_cls_dependencies = self.__find_out_class_dependencies( internal_cls ) i_depend_on_them.update( internal_cls_dependencies ) i_depend_on_them = list( i_depend_on_them ) i_depend_on_them.sort() return i_depend_on_them
def _create_impl( self ): if declarations.is_pointer( self.declaration.type ): return self._generate_for_pointer() elif self.declaration.apply_smart_ptr_wa or self.declaration.use_make_functions: return self._generate_using_functions() else: return self._generate_for_none_pointer()
def set_call_policies_pointee( mb ): # Set the default policy to deal with pointer/reference return types to reference_existing object # as this is the ogrenewt Default. ## NOTE AJM 1/1/07 -- this function not used as change to ref_existing_object.. from pyplusplus import module_creator mem_funs = mb.calldefs () mem_funs.create_with_signature = True #MSVC 7.1 if function has throw modifier. resolver = module_creator.built_in_resolver_t() for mem_fun in mem_funs: if mem_fun.call_policies: continue decl_call_policies = resolver( mem_fun ) if decl_call_policies: mem_fun.call_policies = decl_call_policies continue rtype = declarations.remove_alias( mem_fun.return_type ) if declarations.is_pointer(rtype) or declarations.is_reference(rtype): # mem_fun.call_policies \ # = call_policies.return_value_policy( call_policies.reference_existing_object ) mem_fun.call_policies \ = call_policies.return_value_policy( '::boost::python::return_pointee_value' ) ## now we fix a problem where the getSingleton policy isn't right mb.mem_funs( 'getSingleton' ).call_policies = call_policies.return_value_policy( call_policies.reference_existing_object )
def remove_ref_or_ptr(type_): if declarations.is_pointer(type_): return declarations.remove_pointer(type_) elif declarations.is_reference(type_): return declarations.remove_reference(type_) else: raise TypeError('Type should be reference or pointer, got %s.' % type_)
def _create_with_property(self): name = '"%s"' % self.alias if self.wrapper: make_getter = algorithm.create_identifier( self, '::boost::python::make_function') make_setter = algorithm.create_identifier( self, '::boost::python::make_function') getter_args = [ '(%(getter_type)s)(&%(wfname)s)' % { 'getter_type': self.wrapper.getter_type.decl_string, 'wfname': self.wrapper.getter_full_name } ] setter_args = [ '(%(setter_type)s)(&%(wfname)s)' % { 'setter_type': self.wrapper.setter_type.decl_string, 'wfname': self.wrapper.setter_full_name, } ] if self.declaration.getter_call_policies: getter_args.append( self.declaration.getter_call_policies.create(self)) if declarations.is_pointer(self.declaration.decl_type): getter_args = getter_args[:1] + [ call_policies.return_internal_reference().create(self) ] if not self.declaration.type_qualifiers.has_static: setter_args.append( call_policies.with_custodian_and_ward_postcall( 1, 2).create(self)) has_setter = self.wrapper.has_setter else: make_getter = algorithm.create_identifier( self, '::boost::python::make_getter') make_setter = algorithm.create_identifier( self, '::boost::python::make_setter') getter_args = [ '&' + self.decl_identifier, self.declaration.getter_call_policies.create(self) ] setter_args = ['&' + self.decl_identifier] has_setter = self.declaration.is_read_only getter = '%(mk_func)s(%(args)s)' % { 'mk_func': make_getter, 'args': self.indent(self.PARAM_SEPARATOR, 6).join(getter_args) } setter = None if self.wrapper.has_setter: setter = '%(mk_func)s(%(args)s)' % { 'mk_func': make_setter, 'args': self.indent(self.PARAM_SEPARATOR, 6).join(setter_args) } return self._create_property(name, getter, setter)
def check_type_compatibility(self, fget, fset): #algorithms allows "const" differences between types t1 = fget.return_type t2 = fset.arguments[0].decl_type if declarations.is_same(t1, t2): return True elif declarations.is_pointer(t1) and declarations.is_pointer(t2): t1 = declarations.remove_cv(declarations.remove_pointer(t1)) t2 = declarations.remove_cv(declarations.remove_pointer(t2)) return declarations.is_same(t1, t2) elif declarations.is_reference(t1) and declarations.is_reference(t2): t1 = declarations.remove_cv(declarations.remove_reference(t1)) t2 = declarations.remove_cv(declarations.remove_reference(t2)) return declarations.is_same(t1, t2) else: return False
def check_type_compatibility( self, fget, fset ): #algorithms allows "const" differences between types t1 = fget.return_type t2 = fset.arguments[0].type if declarations.is_same( t1, t2 ): return True elif declarations.is_pointer( t1 ) and declarations.is_pointer( t2 ): t1 = declarations.remove_cv( declarations.remove_pointer( t1 ) ) t2 = declarations.remove_cv( declarations.remove_pointer( t2 ) ) return declarations.is_same( t1, t2 ) elif declarations.is_reference( t1 ) and declarations.is_reference( t2 ): t1 = declarations.remove_cv( declarations.remove_reference( t1 ) ) t2 = declarations.remove_cv( declarations.remove_reference( t2 ) ) return declarations.is_same( t1, t2 ) else: return False
def call_traits( type_ ): """http://boost.org/libs/utility/call_traits.htm""" type_ = declarations.remove_alias( type_ ) if is_immutable( type_ ): return "%s" #pass by value elif declarations.is_reference( type_ ): no_ref = declarations.remove_reference( type_ ) if is_immutable( no_ref ): return "%s" #pass by value else: return "boost::ref(%s)" #pass by ref elif declarations.is_pointer( type_ ) \ and not is_immutable( type_.base ) \ and not declarations.is_pointer( type_.base ): return "boost::python::ptr(%s)" #pass by ptr else: return "%s" #pass by value
def __init__(self, function, arg_ref): """Constructor.""" transformer.transformer_t.__init__( self, function ) self.arg = self.get_argument( arg_ref ) self.arg_index = self.function.arguments.index( self.arg ) if not declarations.is_pointer( self.arg.type ): raise ValueError( '%s\nin order to use "transfer ownership" transformation, argument %s type must be a pointer (got %s).' ) \ % ( function, self.arg_ref.name, arg.type)
def _exportable_impl(self): if not self.parent.name and self.is_wrapper_needed(): #return messages.W1057 % str( self ) return messages.W1058 % str(self) if not self.name: return messages.W1033 if self.bits == 0 and self.name == "": return messages.W1034 if not self.expose_address: if declarations.is_array( self.type) and declarations.array_size(self.type) < 1: return messages.W1045 type_ = declarations.remove_alias(self.type) type_ = declarations.remove_const(type_) if declarations.is_pointer(type_): if not self.expose_address and self.type_qualifiers.has_static: return messages.W1035 if not self.expose_address and python_traits.is_immutable( type_.base): return messages.W1036 units = declarations.decompose_type(type_) ptr2functions = [ unit for unit in units if isinstance(unit, declarations.calldef_type_t) ] if ptr2functions: return messages.W1037 type_ = declarations.remove_pointer(type_) if declarations.class_traits.is_my_case(type_): cls = declarations.class_traits.get_declaration(type_) if not cls.name: return messages.W1038 #if cls.class_type == declarations.CLASS_TYPES.UNION: # return messages.W1061 % ( str( self ), str( cls ) ) if isinstance(self.parent, declarations.class_t): if self.access_type != declarations.ACCESS_TYPES.PUBLIC: return messages.W1039 if declarations.is_array(type_): item_type = declarations.array_item_type(type_) if declarations.is_pointer(item_type): item_type_no_ptr = declarations.remove_pointer(item_type) if python_traits.is_immutable(item_type_no_ptr): return messages.W1056 return ''
def _create_impl(self): if declarations.is_pointer(self.declaration.decl_type): return self._create_with_property() if declarations.is_reference(self.declaration.decl_type): return self._create_with_property() elif self.declaration.apply_smart_ptr_wa or self.declaration.use_make_functions: return self._create_with_property() else: return self._create_with_def()
def visit_variable(self): self.__types_db.update( self.curr_decl ) self.__dependencies_manager.add_exported( self.curr_decl ) if self.curr_decl.expose_address: creator_type = None if isinstance( self.curr_decl.parent, declarations.namespace_t ): creator_type = code_creators.global_variable_addressof_t else: creator_type = code_creators.member_variable_addressof_t self.curr_code_creator.adopt_creator( creator_type(self.curr_decl) ) return if not self.curr_decl.expose_value: return if declarations.is_array( self.curr_decl.type ): if self._register_array_1( self.curr_decl.type ): array_1_registrator = code_creators.array_1_registrator_t( array_type=self.curr_decl.type ) self.curr_code_creator.adopt_creator( array_1_registrator ) if isinstance( self.curr_decl.parent, declarations.namespace_t ): maker = None wrapper = None if declarations.is_array( self.curr_decl.type ): wrapper = code_creators.array_gv_wrapper_t( variable=self.curr_decl ) maker = code_creators.array_gv_t( variable=self.curr_decl, wrapper=wrapper ) else: maker = code_creators.global_variable_t( variable=self.curr_decl ) if wrapper: self.__extmodule.adopt_declaration_creator( wrapper ) else: maker = None wrapper = None if self.curr_decl.bits != None: wrapper = code_creators.bit_field_wrapper_t( variable=self.curr_decl ) maker = code_creators.bit_field_t( variable=self.curr_decl, wrapper=wrapper ) elif declarations.is_array( self.curr_decl.type ): wrapper = code_creators.array_mv_wrapper_t( variable=self.curr_decl ) maker = code_creators.array_mv_t( variable=self.curr_decl, wrapper=wrapper ) elif declarations.is_pointer( self.curr_decl.type ): wrapper = code_creators.member_variable_wrapper_t( variable=self.curr_decl ) maker = code_creators.member_variable_t( variable=self.curr_decl, wrapper=wrapper ) elif declarations.is_reference( self.curr_decl.type ): if None is self.curr_decl.getter_call_policies: self.curr_decl.getter_call_policies = self.__call_policies_resolver( self.curr_decl, 'get' ) if None is self.curr_decl.setter_call_policies: self.curr_decl.setter_call_policies = self.__call_policies_resolver( self.curr_decl, 'set' ) wrapper = code_creators.mem_var_ref_wrapper_t( variable=self.curr_decl ) maker = code_creators.mem_var_ref_t( variable=self.curr_decl, wrapper=wrapper ) self.__opaque_types_manager.register_opaque( maker, self.curr_decl ) else: maker = code_creators.member_variable_t( variable=self.curr_decl ) if wrapper: self.curr_code_creator.wrapper.adopt_creator( wrapper ) self.curr_code_creator.adopt_creator( maker )
def _readme_impl(self): def is_double_ptr(type_): #check for X** if not declarations.is_pointer(type_): return False base = declarations.remove_pointer(type_) return declarations.is_pointer(base) def suspicious_type(type_): if not declarations.is_reference(type_): return False type_no_ref = declarations.remove_reference(type_) return not declarations.is_const( type_no_ref ) \ and ( declarations.is_fundamental( type_no_ref ) or declarations.is_enum( type_no_ref ) ) msgs = [] #TODO: functions that takes as argument pointer to pointer to smth, could not be exported #see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr if len(self.arguments) > calldef_t.BOOST_PYTHON_MAX_ARITY: msgs.append( messages.W1007 % (calldef_t.BOOST_PYTHON_MAX_ARITY, len(self.arguments))) if self.transformations: #if user defined transformation, than I think it took care of the problems ft = self.transformations[0] if ft.alias == ft.unique_name: msgs.append(messages.W1044 % ft.alias) return msgs if suspicious_type(self.return_type) and None is self.call_policies: msgs.append(messages.W1008) if ( declarations.is_pointer( self.return_type ) or is_double_ptr( self.return_type ) ) \ and None is self.call_policies: msgs.append(messages.W1050 % str(self.return_type)) for index, arg in enumerate(self.arguments): if suspicious_type(arg.type): msgs.append(messages.W1009 % (arg.name, index)) if is_double_ptr(arg.type): msgs.append(messages.W1051 % (arg.name, index, str(arg.type))) if False == self.overridable: msgs.append(self._non_overridable_reason) problematics = algorithm.registration_order.select_problematics(self) if problematics: tmp = [] for f in problematics: tmp.append(os.linesep + '\t' + str(f)) msgs.append(messages.W1010 % os.linesep.join(tmp)) return msgs
def setDefaultCallPolicies(ns): # Set the default policy to deal with pointer/reference return types to reference_existing object # as this is the CEGUI Default. mem_funs = ns.calldefs() mem_funs.create_with_signature = True #Generated code will not compile on #MSVC 7.1 if function has throw modifier. for mem_fun in mem_funs: if mem_fun.call_policies: continue if declarations.is_pointer (mem_fun.return_type) or declarations.is_reference (mem_fun.return_type): mem_fun.call_policies = call_policies.return_value_policy(call_policies.reference_existing_object)
def _readme_impl(self): def is_double_ptr(type_): # check for X** if not declarations.is_pointer(type_): return False base = declarations.remove_pointer(type_) return declarations.is_pointer(base) def suspicious_type(type_): if not declarations.is_reference(type_): return False type_no_ref = declarations.remove_reference(type_) return not declarations.is_const(type_no_ref) and ( declarations.is_fundamental(type_no_ref) or declarations.is_enum(type_no_ref) ) msgs = [] # TODO: functions that takes as argument pointer to pointer to smth, could not be exported # see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr if len(self.arguments) > calldef_t.BOOST_PYTHON_MAX_ARITY: msgs.append(messages.W1007 % (calldef_t.BOOST_PYTHON_MAX_ARITY, len(self.arguments))) if self.transformations: # if user defined transformation, than I think it took care of the problems ft = self.transformations[0] if ft.alias == ft.unique_name: msgs.append(messages.W1044 % ft.alias) return msgs if suspicious_type(self.return_type) and None is self.call_policies: msgs.append(messages.W1008) if ( declarations.is_pointer(self.return_type) or is_double_ptr(self.return_type) ) and None is self.call_policies: msgs.append(messages.W1050 % str(self.return_type)) for index, arg in enumerate(self.arguments): if suspicious_type(arg.type): msgs.append(messages.W1009 % (arg.name, index)) if is_double_ptr(arg.type): msgs.append(messages.W1051 % (arg.name, index, str(arg.type))) if False == self.overridable: msgs.append(self._non_overridable_reason) problematics = algorithm.registration_order.select_problematics(self) if problematics: tmp = [] for f in problematics: tmp.append(os.linesep + "\t" + str(f)) msgs.append(messages.W1010 % os.linesep.join(tmp)) return msgs
def _exportable_impl( self ): if not self.parent.name and self.is_wrapper_needed(): #return messages.W1057 % str( self ) return messages.W1058 % str( self ) if not self.name: return messages.W1033 if self.bits == 0 and self.name == "": return messages.W1034 if not self.expose_address: if declarations.is_array( self.type ) and declarations.array_size( self.type ) < 1: return messages.W1045 type_ = declarations.remove_alias( self.type ) type_ = declarations.remove_const( type_ ) if declarations.is_pointer( type_ ): if not self.expose_address and self.type_qualifiers.has_static: return messages.W1035 if not self.expose_address and python_traits.is_immutable( type_.base ): return messages.W1036 units = declarations.decompose_type( type_ ) ptr2functions = filter( lambda unit: isinstance( unit, declarations.calldef_type_t ) , units ) if ptr2functions: return messages.W1037 type_ = declarations.remove_pointer( type_ ) if declarations.class_traits.is_my_case( type_ ): cls = declarations.class_traits.get_declaration( type_ ) if not cls.name: return messages.W1038 #if cls.class_type == declarations.CLASS_TYPES.UNION: # return messages.W1061 % ( str( self ), str( cls ) ) if isinstance( self.parent, declarations.class_t ): if self.access_type != declarations.ACCESS_TYPES.PUBLIC: return messages.W1039 if declarations.is_array( type_ ): item_type = declarations.array_item_type( type_ ) if declarations.is_pointer( item_type ): item_type_no_ptr = declarations.remove_pointer( item_type ) if python_traits.is_immutable( item_type_no_ptr ): return messages.W1056 return ''
def is_related( t1, t2 ): """Check whether two types\\classes t1 and t2 could introduce the problem""" if declarations.is_pointer( t1 ) and declarations.is_pointer( t2 ): return registration_order.is_related( declarations.remove_pointer( t1 ) , declarations.remove_pointer( t2 ) ) elif declarations.is_pointer( t1 ) and not declarations.is_pointer( t2 ): t1 = declarations.remove_cv( declarations.remove_pointer( t1 ) ) t2 = declarations.remove_cv( t2 ) if declarations.is_same( t1, t2 ): return 1 elif not declarations.is_pointer( t1 ) and declarations.is_pointer( t2 ): t1 = declarations.remove_cv( t1 ) t2 = declarations.remove_cv( declarations.remove_pointer( t2 ) ) if declarations.is_same( t1, t2 ): return -1 else: #not is_pointer( t1 ) and not is_pointer( t2 ): if declarations.is_integral( t1 ) and not declarations.is_bool( t1 ) \ and declarations.is_bool( t2 ): return -1 elif declarations.is_bool( t1 ) \ and declarations.is_integral( t2 ) and not declarations.is_bool( t2 ): return 1 else: pass return None
def is_related(t1, t2): """Check whether two types\\classes t1 and t2 could introduce the problem""" if declarations.is_pointer(t1) and declarations.is_pointer(t2): return registration_order.is_related( declarations.remove_pointer(t1), declarations.remove_pointer(t2)) elif declarations.is_pointer(t1) and not declarations.is_pointer(t2): t1 = declarations.remove_cv(declarations.remove_pointer(t1)) t2 = declarations.remove_cv(t2) if declarations.is_same(t1, t2): return 1 elif not declarations.is_pointer(t1) and declarations.is_pointer(t2): t1 = declarations.remove_cv(t1) t2 = declarations.remove_cv(declarations.remove_pointer(t2)) if declarations.is_same(t1, t2): return -1 else: #not is_pointer( t1 ) and not is_pointer( t2 ): if declarations.is_integral( t1 ) and not declarations.is_bool( t1 ) \ and declarations.is_bool( t2 ): return -1 elif declarations.is_bool( t1 ) \ and declarations.is_integral( t2 ) and not declarations.is_bool( t2 ): return 1 else: pass return None
def fix_pointer_returns(classes, pointee_types=None, ignore_names=None): """ Change out functions that return a variety of pointer to base types and instead have them return the address the pointer is pointing to (the pointer value) This allow us to use CTypes to handle in memory buffers from Python Also - if documentation has been set then ignore the class/function as it means it's been tweaked else where """ if pointee_types is None: pointee_types = [ 'unsigned int', 'int', 'float', 'double', 'char', 'unsigned char' ] if ignore_names is None: ignore_names = [] for cls in classes: for fun in cls.member_functions(allow_empty=True): if declarations.is_pointer( fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith( i) and not fun.documentation: if not fun.name in ignore_names: decl_logger.info( "Excluding (function): %s as it returns (pointer) %s" % (fun, i)) fun.exclude() for fun in cls.member_operators(allow_empty=True): if declarations.is_pointer( fun.return_type) and not fun.documentation: for i in pointee_types: if fun.return_type.decl_string.startswith( i) and not fun.documentation: decl_logger.info("Excluding (operator): %s" % fun) fun.exclude()
def return_range(function, get_size_class, value_policies=None): """create `Py++` defined return_range call policies code generator""" r_type = function.return_type if not declarations.is_pointer(r_type): raise TypeError('Function "%s" return type should be pointer, got "%s"' % r_type.decl_string) value_type = declarations.remove_pointer(r_type) if None is value_policies: if python_traits.is_immutable(value_type): value_policies = default_call_policies() else: raise RuntimeError("return_range call policies requieres specification of value_policies") return return_range_t(get_size_class, value_type, value_policies)
def Set_Call_Policies( mb ): """ set the return call policies on classes that this hasn't already been done for. Set the default policy to deal with pointer/reference return types to reference_existing object """ mem_funs = mb.calldefs () mem_funs.create_with_signature = True #Generated code will not compile on #MSVC 7.1 if function has throw modifier. 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) ): mem_fun.call_policies = call_policies.return_value_policy( call_policies.reference_existing_object )
def test(self): """ Test the find_noncopyable_vars function """ # The ptr1 variable in the holder struct can be copied, # but not the ptr2 variable holder = self.global_ns.class_("holder") nc_vars = declarations.find_noncopyable_vars(holder) self.assertEqual(len(nc_vars), 1) self.assertEqual(nc_vars[0].name, "ptr2") self.assertTrue(declarations.is_pointer(nc_vars[0].decl_type)) self.assertTrue(declarations.is_const(nc_vars[0].decl_type))
def applyDefaultReturnPolicies(functions): for f in functions: if not f.call_policies: return_type = f.return_type if declarations.is_reference(return_type) or declarations.is_pointer(return_type): type_info = return_type type_info = declarations.remove_pointer(type_info) type_info = declarations.remove_reference(type_info) type_info = declarations.remove_const(type_info) # Se il tipo non e' esposto (potrebbe essere una classe, ma non ci sono informazioni perche' la dichiarazione non e' stata incontrata), viene gestito tramite return_opaque_pointer if declarations.is_class(type_info): f.call_policies = call_policies.return_value_policy(call_policies.reference_existing_object) else: f.call_policies = call_policies.return_value_policy(call_policies.return_opaque_pointer)
def is_wrapper_needed(self): """returns an explanation( list of str ) why wrapper is needed. If wrapper is not needed than [] will be returned. """ explanation = [] if self.bits: explanation.append( messages.W1024 % self.name ) if declarations.is_pointer( self.type ): explanation.append( messages.W1025 % self.name ) if declarations.is_reference( self.type ): explanation.append( messages.W1026 % self.name ) if declarations.is_array( self.type ): explanation.append( messages.W1027 % self.name) return explanation
def is_wrapper_needed(self): """returns an explanation( list of str ) why wrapper is needed. If wrapper is not needed than [] will be returned. """ explanation = [] if self.bits: explanation.append( messages.W1024 % self.name ) if declarations.is_pointer( self.decl_type ): explanation.append( messages.W1025 % self.name ) if declarations.is_reference( self.decl_type ): explanation.append( messages.W1026 % self.name ) if declarations.is_array( self.decl_type ): explanation.append( messages.W1027 % self.name) return explanation
def _get_call_policies( self ): if self.__call_policies: return self.__call_policies if self.container_traits not in declarations.sequential_container_traits: #TODO: find out why map's don't like the policy return self.__call_policies element_type = None try: element_type = self.element_type except: return if declarations.is_const( element_type ): element_type = declarations.remove_const( element_type ) if declarations.is_pointer( element_type ): self.__call_policies = call_policies.return_internal_reference() return self.__call_policies
def _get_call_policies(self): if self.__call_policies: return self.__call_policies if self.container_traits not in declarations.sequential_container_traits: # TODO: find out why map's don't like the policy return self.__call_policies element_type = None try: element_type = self.element_type except: return if declarations.is_const(element_type): element_type = declarations.remove_const(element_type) if declarations.is_pointer(element_type): self.__call_policies = call_policies.return_internal_reference() return self.__call_policies
def getTypePPA(ptype): if decls.is_pointer(ptype): return TypedefSeq(ptype) # specify return value elif decls.is_fundamental(ptype): return [] elif decls.is_class(ptype): return pyscope.CClass(ptype, pyresolvable.resolveNS(ptype)) # unknown / not yet implemented type. # This is treated as class => there may be some complications. else: print "WARNING: unknown type:" + str(ptype) return pyscope.CClass(ptype, pyresolvable.resolveNS(ptype))
def getTypePPA(ptype): if decls.is_pointer(ptype): return TypedefSeq(ptype) # specify return value elif decls.is_fundamental(ptype): return [] elif decls.is_class(ptype): return pyscope.CClass(ptype, pyresolvable.resolveNS(ptype)) # unknown / not yet implemented type. # This is treated as class => there may be some complications. else: print 'WARNING: unknown type:' + str(ptype) return pyscope.CClass(ptype, pyresolvable.resolveNS(ptype))
def return_range(function, get_size_class, value_policies=None): """create Py++ defined return_range call policies code generator""" r_type = function.return_type if not declarations.is_pointer(r_type): raise TypeError( 'Function "%s" return type should be pointer, got "%s"' % r_type.decl_string) value_type = declarations.remove_pointer(r_type) if None is value_policies: if python_traits.is_immutable(value_type): value_policies = default_call_policies() else: raise RuntimeError( "return_range call policies requieres specification of value_policies" ) return return_range_t(get_size_class, value_type, value_policies)
def is_wrapper_needed(self): """returns an explanation( list of str ) why wrapper is needed. If wrapper is not needed than [] will be returned. """ explanation = [] if self.wrapper_code: explanation.append(messages.W1020) if self.null_constructor_body: explanation.append(messages.W1021) if self.copy_constructor_body: explanation.append(messages.W1022) redefined_funcs = self.redefined_funcs() if redefined_funcs: funcs = map(lambda f: f.name, redefined_funcs) explanation.append(messages.W1023 % ', '.join(funcs)) for member in self.get_exportable_members(): if isinstance(member, declarations.destructor_t): continue if isinstance(member, declarations.variable_t): if member.bits: explanation.append(messages.W1024 % member.name) if declarations.is_pointer(member.type): explanation.append(messages.W1025 % member.name) if declarations.is_reference(member.type): explanation.append(messages.W1026 % member.name) if declarations.is_array(member.type): explanation.append(messages.W1027 % member.name) if isinstance(member, declarations.class_t) and member.is_wrapper_needed(): explanation.append(messages.W1028 % member.name) if isinstance(member, declarations.calldef_t): if isinstance(member, declarations.constructor_t) and member.body: explanation.append(messages.W1029) if member.virtuality != VIRTUALITY_TYPES.NOT_VIRTUAL: explanation.append(messages.W1030 % member.name) if member.access_type in (ACCESS_TYPES.PROTECTED, ACCESS_TYPES.PRIVATE): explanation.append(messages.W1031 % member.name) return explanation
def wrap_one_call_policy(fn): rt = fn.return_type if fn.return_type.decl_string == "char const *": return # use default for strings if fn.return_type.decl_string == "char *": return # use default for strings elif fn.return_type.decl_string == "void *": return # use default for void pointers elif fn.return_type.decl_string == "::GLvoid const *": return # use default for void pointers parent_ref = declarations.reference_t(declarations.declarated_t(fn.parent)) if declarations.is_reference(rt): # Need type without reference for next type checks nonref_rt = rt.base if declarations.is_arithmetic(nonref_rt) or declarations.is_enum( nonref_rt): # returning const& double can cause compile trouble if return_internal_reference is used if declarations.is_const(nonref_rt): fn.call_policies = return_value_policy(copy_const_reference) return # int& might need to be copy_non_const_reference... else: fn.call_policies = return_value_policy( copy_non_const_reference) return # Const string references should be copied to python strings if declarations.is_std_string(nonref_rt) and declarations.is_const( nonref_rt): fn.call_policies = return_value_policy(copy_const_reference) return # Returning reference to this same class looks like return_self() [does this always work?] if declarations.is_same(parent_ref, rt): fn.call_policies = return_self() return elif declarations.is_pointer(rt): # Clone methods if re.search(r'^clone', fn.name): fn.call_policies = return_value_policy(reference_existing_object) return else: return # Everything else probably returns an internal reference fn.call_policies = return_internal_reference() return
def find_out_opaque_decl(type_, ensure_opaque_decl): naked_type = declarations.remove_cv(type_) if not declarations.is_pointer(naked_type): return None naked_type = declarations.remove_pointer(declarations.remove_cv(type_)) if decl_wrappers.python_traits.is_immutable(naked_type): return None #immutable types could not be opaque decl = None if declarations.is_class(naked_type): decl = declarations.class_traits.get_declaration(naked_type) elif declarations.is_class_declaration(naked_type): #class declaration: decl = declarations.class_declaration_traits.get_declaration( naked_type) else: return None if ensure_opaque_decl: if decl.opaque: return decl else: return None else: return decl
def __find_out_is_read_only(self): type_ = declarations.remove_alias( self.decl_type ) if isinstance( type_, declarations.const_t ): return True if declarations.is_pointer( type_ ): type_ = declarations.remove_pointer( type_ ) if declarations.is_reference( type_ ): type_ = declarations.remove_reference( type_ ) if isinstance( type_, declarations.const_t ): return True if self.apply_smart_ptr_wa: return False #all smart pointers has assign operator if isinstance( type_, declarations.declarated_t ) \ and isinstance( type_.declaration, declarations.class_t ) \ and not declarations.has_public_assign( type_.declaration ): return True return False
def fix_ptr_fun(fun, pointee_types=None, ignore_names=None, Exclude=False): """ Allows to exclude or mark with a warning functions which take pointers as arguments It ignores already documented functions, because those have been fixed elsewhere """ if pointee_types is None: pointee_types = [] if ignore_names is None: ignore_names = [] if fun.documentation or fun.ignore: # means it's been tweaked somewhere else return for n in ignore_names: if n in fun.name: return for arg in fun.arguments: # and "const" not in arg.type.decl_string: if declarations.is_pointer(arg.type): for i in pointee_types: if arg.type.decl_string.startswith(i): if Exclude: decl_logger.info( "Excluding: %s due to pointer argument %s" % (fun, arg.type.decl_string)) fun.exclude() return else: decl_logger.info( "Function has pointer argument: %s %s" % (fun, arg.type.decl_string)) fun.documentation = docit( "SUSPECT - MAYBE BROKEN due to pointer argument", "....", "...") return