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 ) )
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 is_immutable( type_ ): """returns True, if type_ represents Python immutable type""" return declarations.is_fundamental( type_ ) \ or declarations.is_enum( type_ ) \ or declarations.is_std_string( type_ ) \ or declarations.is_std_wstring( type_ ) \ or declarations.smart_pointer_traits.is_smart_pointer( type_ )
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) )
def _convert_opaque_to_token(x): """ convert either a string from re or a value from pygccxml to a struct token """ if type(x) is str: return { "BOOL": "?", "UINT8_T": "B", "INT8_T": "b", "UINT16_T": "H", "INT16_T": "h", "UINT32_T": "I", "INT32_T": "i", "UINT64_T": "Q", "INT64_T": "q", "FLOAT": "f", "DOUBLE": "d" }[x.upper()] elif isinstance(x, declarations.declarated_t) and not declarations.is_enum(x): return _convert_opaque_to_token(declarations.remove_alias(x)) elif declarations.is_integral(x) or declarations.is_enum(x): basetoken = {1: "b", 2: "h", 4: "i", 8: "q"}[int(x.byte_size)] try: if "unsigned" in x.CPPNAME: basetoken = basetoken.upper() if "bool" in x.CPPNAME: basetoken = '?' except AttributeError: pass return basetoken elif declarations.is_floating_point(x): if isinstance(x, declarations.float_t): return "f" else: return "d" elif declarations.is_array(x): basetoken = _convert_opaque_to_token(declarations.array_item_type(x)) return basetoken * x.size else: raise ValueError("unknown instance: " + repr(x))
def __is_unqualified_enum(self, func, arg): type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) if not declarations.is_enum(type_): return False enum_type = declarations.enum_declaration(type_) # GCCXML does not qualify an enum value in the default argument # but CastXML does. Split the default value and use only the # enum value for fixing it. return enum_type.has_value_name(arg.default_value.split('::')[-1])
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 __is_unqualified_enum(self, func, arg): type_ = declarations.remove_reference(declarations.remove_cv(arg.type)) if not declarations.is_enum(type_): return False enum_type = declarations.enum_declaration(type_) # GCCXML does not qualify an enum value in the default argument # but CastXML does. Split the default value and use only the # enum value for fixing it. return enum_type.has_value_name( arg.default_value.split('::')[-1])
def customize_module( mb ): extmodule = mb.code_creator extmodule.license = customization_data.license # Insert a custom init call extmodule.adopt_creator( code_creators.custom_text_t('extern void InitialiseTnFOXPython();\n\n'), len(extmodule.creators)-1) extmodule.body.adopt_creator( code_creators.custom_text_t(' InitialiseTnFOXPython();\n\n'), 0) # Remove all standard headers in favour of precompiled header includes = filter( lambda creator: isinstance( creator, code_creators.include_t ) , extmodule.creators ) map( lambda creator: extmodule.remove_creator( creator ), includes ) position = extmodule.last_include_index() + 1 extmodule.adopt_creator( code_creators.namespace_using_t('::FX'), position ) extmodule.user_defined_directories.append( settings.generated_files_dir ) extmodule.adopt_include( code_creators.include_t( header='../common.h' ) ) extmodule.precompiled_header = '../common.h' extmodule.adopt_include( code_creators.include_t( header='../patches.cpp.h' ) ) # Fix bug in gccxml where default args with function as value gain an extra () try: constr = mb.constructor( 'FXPrimaryButton', arg_types=[None]*15 ) constr.arguments[10].default_value = '(FX::FXWindow::defaultPadding() * 4)' constr.arguments[11].default_value = '(FX::FXWindow::defaultPadding() * 4)' except: pass # Patch default args with enums to be number (to avoid undeclared enum problem) def args_declaration_wa( self ): args = [] for index, arg in enumerate( self.declaration.arguments ): result = arg.type.decl_string + ' ' + self.argument_name(index) if arg.default_value: result += '=%s' % arg.wrapper_default_value args.append( result ) if len( args ) == 1: return args[ 0 ] return ', '.join( args ) code_creators.calldef.calldef_wrapper_t.args_declaration = args_declaration_wa allfuncs = mb.calldefs() for func in allfuncs: #print type(func), type(func.parent), func for arg in func.arguments: if not arg.default_value: continue arg.wrapper_default_value = arg.default_value if not declarations.is_enum( arg.type ): continue enum_ = declarations.enum_declaration( arg.type ) if isinstance( enum_.parent, declarations.namespace_t ): continue #global enum # Be lazy, and just lookup the last part value = arg.default_value[ arg.default_value.rfind('::')+2: ] arg.default_value = arg.type.declaration.values[ value ] + '/*' + arg.default_value + '*/'
def __should_use_enum_wa(self, arg): global use_enum_workaround if not declarations.is_enum(arg.type): return False if use_enum_workaround: return True #enum belongs to the class we are working on if self.__decl.parent is declarations.enum_declaration( arg.type ).parent \ and isinstance( self.__decl, declarations.constructor_t ): return True return False
def __should_use_enum_wa( self, arg ): global use_enum_workaround if not declarations.is_enum( arg.type ): return False if use_enum_workaround: return True #enum belongs to the class we are working on if self.__decl.parent is declarations.enum_declaration( arg.type ).parent \ and isinstance( self.__decl, declarations.constructor_t ): return True return False
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 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 check_args_exportable ( function, ns ): """ Look at each argument in the function and determine that we have exported it or it's a special. """ ret = True Specials = ['::Ogre::String'] for a in function.arguments: rawarg = declarations.remove_declarated( declarations.remove_const( declarations.remove_reference( declarations.remove_pointer ( a.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 declarations.is_enum(rawarg): pass elif 'Ogre::' in a.type.decl_string: # assume it's a class and needs checking name = a.type.decl_string.split()[0] # let's grab the actual class name if name in Specials: # we know that the classes in specials DO exist pass else: try: tcls = ns.class_(name) if not tcls.exportable or tcls.ignore or type ( tcls.parent ) != decl_wrappers.namespace_wrapper.namespace_t: ## print "check_args_exportable: NOT EXPORTABLE:", tcls, tcls.exportable, tcls.ignore , type ( tcls.parent ) ret = False break else: pass # print name, "IS exportable" except: print "check_args_exportable: unable to find:", name ret = False else: print "check_args_exportable: NOT SURE...", a, a.type, type(a.type) return ret
def _create_member_list(struct_info): new_type_members = [] for i in struct_info.variables(): if i.type_qualifiers.has_static: continue bitfield = None enumer = None if declarations.is_integral(i.decl_type): try: for enumerator in struct_info.enumerations(): if enumerator.byte_size != declarations.remove_alias( i.decl_type).byte_size: continue elif enumerator.name != snake_to_camel(i.name): continue else: bitfield = enumerator.get_name2value_dict() break except RuntimeError: bitfield = None elif declarations.is_enum(i.decl_type): try: enumer = global_namespace.enumeration( i.decl_type.decl_string).get_name2value_dict() except RuntimeError: enumer = {} if declarations.is_class(i.decl_type): new_type_members.append( DeclaredMemberStruct( i.name, _create_member_list(i.decl_type.declaration))) else: new_type_members.append( DeclaredMember(i.name, _convert_opaque_to_token(i.decl_type), bitfield=bitfield, enumer=enumer)) return new_type_members
def _get_has_setter(self): no_ref = declarations.remove_reference(self.declaration.decl_type) no_const = declarations.remove_const(no_ref) base_type = declarations.remove_alias(no_const) if declarations.is_const(no_ref): return False if declarations.is_enum(base_type): return True if python_traits.is_immutable(self._get_var_type()): return True 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 __is_unqualified_enum(self, func, arg): type_ = declarations.remove_reference( declarations.remove_cv( arg.type ) ) if not declarations.is_enum( type_ ): return False enum_type = declarations.enum_declaration( type_ ) return enum_type.has_value_name( arg.default_value )