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 ManualFixes ( mb ): global_ns = mb.global_ns main_ns = global_ns funcs = [ '::ssgBranch::getByName' ,'::ssgBranch::getByPath' ,'::ssgEntity::getByName' ,'::ssgEntity::getByPath' ] # for f in funcs: # main_ns.member_functions(f).call_policies = call_policies.default_call_policies() # bug in Py++ where is uses the wrong call policies on a transformed function for fun in main_ns.member_functions(allow_empty=True): if fun.transformations: if declarations.is_pointer(fun.return_type ) : rawarg = declarations.remove_declarated( declarations.remove_const( declarations.remove_reference( declarations.remove_pointer ( fun.return_type )))) if not declarations.is_arithmetic (rawarg) and not declarations.is_void(rawarg): fun.call_policies = call_policies.default_call_policies() print "Changed call policies on ", fun
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, "...")