示例#1
0
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
示例#2
0
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
示例#5
0
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, "...")