def create_default(self): cntrl = self.controller.default_controller make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object') make_tuple = algorithm.create_identifier(self, 'boost::python::make_tuple') tmpl_values = dict() tmpl_values['unique_function_name'] = self.default_name() tmpl_values['return_type'] = cntrl.wrapper_return_type.decl_string tmpl_values['arg_declarations'] = self.args_default_declaration() tmpl_values['wrapper_class'] = self.parent.wrapper_alias tmpl_values['wrapped_class'] = declarations.full_name( self.declaration.parent) tmpl_values['wrapped_inst'] = cntrl.inst_arg.name tmpl_values['wrapped_inst_constness'] = '' if declarations.is_const( declarations.remove_reference(cntrl.inst_arg.type)): tmpl_values['wrapped_inst_constness'] = 'const' decl_vars = cntrl.variables[:] if not declarations.is_void(self.declaration.return_type): decl_vars.append(cntrl.result_variable) tmpl_values['declare_variables'] \ = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) , decl_vars ) ) tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join(cntrl.pre_call)) tmpl_values['save_result'] = '' if not declarations.is_void(self.declaration.return_type): tmpl_tmp = '%(result_var_name)s = ' if declarations.is_reference(self.declaration.return_type): tmpl_tmp = tmpl_tmp + '&' tmpl_values['save_result'] = tmpl_tmp % dict( result_var_name=cntrl.result_variable.name) tmpl_values['function_name'] = self.declaration.name tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions) return_stmt_creator = calldef_utils.return_stmt_creator_t( self, cntrl, cntrl.result_variable, cntrl.return_variables) tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join(cntrl.post_call)) if return_stmt_creator.pre_return_code: tmpl_values['post_call'] \ = os.linesep.join([ tmpl_values['post_call'] , self.indent( return_stmt_creator.pre_return_code )]) tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement) f_def = cntrl.template.substitute(tmpl_values) return remove_duplicate_linesep(f_def)
def create_default(self): cntrl = self.controller.default_controller make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) tmpl_values = dict() tmpl_values['unique_function_name'] = self.default_name() tmpl_values['return_type'] = cntrl.wrapper_return_type.decl_string tmpl_values['arg_declarations'] = self.args_default_declaration() tmpl_values['wrapper_class'] = self.parent.wrapper_alias tmpl_values['wrapped_class'] = declarations.full_name( self.declaration.parent ) tmpl_values['wrapped_inst'] = cntrl.inst_arg.name tmpl_values['wrapped_inst_constness'] = '' if declarations.is_const( declarations.remove_reference( cntrl.inst_arg.type ) ): tmpl_values['wrapped_inst_constness'] = 'const' decl_vars = cntrl.variables[:] if not declarations.is_void( self.declaration.return_type ): decl_vars.append( cntrl.result_variable ) tmpl_values['declare_variables'] \ = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) , decl_vars ) ) tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) tmpl_values['save_result'] = '' if not declarations.is_void( self.declaration.return_type ): tmpl_tmp = '%(result_var_name)s = ' if declarations.is_reference( self.declaration.return_type ): tmpl_tmp = tmpl_tmp + '&' tmpl_values['save_result'] = tmpl_tmp % dict( result_var_name=cntrl.result_variable.name ) tmpl_values['function_name'] = self.declaration.name tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) return_stmt_creator = calldef_utils.return_stmt_creator_t( self , cntrl , cntrl.result_variable , cntrl.return_variables ) tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) if return_stmt_creator.pre_return_code: tmpl_values['post_call'] \ = os.linesep.join([ tmpl_values['post_call'] , self.indent( return_stmt_creator.pre_return_code )]) tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) f_def = cntrl.template.substitute(tmpl_values) return remove_duplicate_linesep( f_def )
def restype_code(self): if not declarations.is_void(self.ftype.return_type): return ctypes_formatter.as_ctype( self.ftype.return_type, self.top_parent.treat_char_ptr_as_binary_data) else: return ''
def statement( self ): if None is self.__return_stmt: stmt = '' bpl_object = algorithm.create_identifier( self.__creator, 'boost::python::object' ) make_tuple = algorithm.create_identifier( self.__creator, 'boost::python::make_tuple' ) make_object = algorithm.create_identifier( self.__creator, 'pyplusplus::call_policies::make_object' ) if not declarations.is_void( self.__function.return_type ): if self.__function.call_policies.is_default(): self.__return_vars.insert( 0, self.__result_var.name ) else: self.__return_vars.insert( 0 , declarations.call_invocation.join( declarations.templates.join( make_object , [self.__call_policy_alias, self.__result_var.type.decl_string] ) , [self.__result_var.name] ) ) if 0 == len( self.__return_vars ): pass elif 1 == len( self.__return_vars ): stmt = bpl_object + '( %s )' % self.__return_vars[ 0 ] else: # 1 < stmt = declarations.call_invocation.join( make_tuple, self.__return_vars ) if self.__creator.LINE_LENGTH < len( stmt ): stmt = declarations.call_invocation.join( make_tuple , self.__return_vars , os.linesep + self.__creator.indent( self.__creator.PARAM_SEPARATOR, 6 ) ) if stmt: stmt = 'return ' + stmt + ';' self.__return_stmt = stmt return self.__return_stmt
def statement( self ): if None is self.__return_stmt: stmt = '' bpl_object = algorithm.create_identifier( self.__creator, 'boost::python::object' ) make_tuple = algorithm.create_identifier( self.__creator, 'boost::python::make_tuple' ) make_object = algorithm.create_identifier( self.__creator, 'pyplusplus::call_policies::make_object' ) if not declarations.is_void( self.__function.return_type ): if self.__function.call_policies.is_default(): self.__return_vars.insert( 0, self.__result_var.name ) else: self.__return_vars.insert( 0 , declarations.call_invocation.join( declarations.templates.join( make_object , [self.__call_policy_alias, self.__result_var.type.decl_string] ) , [self.__result_var.name] ) ) if 0 == len( self.__return_vars ): pass elif 1 == len( self.__return_vars ): stmt = bpl_object + '( %s )' % self.__return_vars[ 0 ] else: # 1 < stmt = declarations.call_invocation.join( make_tuple, self.__return_vars ) if self.__creator.LINE_LENGTH < len( stmt ): stmt = declarations.call_invocation.join( make_tuple , self.__return_vars , os.linesep + self.__creator.indent( self.__creator.PARAM_SEPARATOR, 6 ) ) if stmt: stmt = 'return ' + stmt + ';' self.__return_stmt = stmt return self.__return_stmt
def AddWrapReg( mb, cls_name, declaration, args_mod_in ): if type(cls_name) != str: cls = cls_name cls_name = cls.name # or alias? else: cls = mb.class_(cls_name) # Create a wrapper class inst wrapper = calldef.mem_fun_v_wrapper_t( declaration ) template = [] # NOTE: Comparing directly gives problems template.append( '%(override)s func_%(alias)s = this->get_override( "%(alias)s" );' ) template.append( 'if( func_%(alias)s.ptr() != Py_None )' ) template.append( wrapper.indent('try {' ) ) template.append( wrapper.indent(wrapper.indent('%(return_)sfunc_%(alias)s( %(args_mod_in)s );' ) ) ) template.append( wrapper.indent('} catch(...) {') ) template.append( wrapper.indent(wrapper.indent('PyErr_Print();')) ) template.append( wrapper.indent(wrapper.indent('%(return_)sthis->%(wrapped_class)s::%(name)s( %(args)s );') ) ) template.append( wrapper.indent( '}' ) ) template.append( 'else' ) template.append( wrapper.indent('%(return_)sthis->%(wrapped_class)s::%(name)s( %(args)s );') ) template = os.linesep.join( template ) return_ = '' if not declarations.is_void( wrapper.declaration.return_type ): return_ = 'return ' answer = [ wrapper.create_declaration(wrapper.declaration.partial_name) + '{' ] answer.append( wrapper.indent( template % { 'override' : wrapper.override_identifier() , 'name' : wrapper.declaration.partial_name , 'alias' : wrapper.declaration.alias , 'return_' : return_ , 'args' : wrapper.function_call_args() , 'args_mod_in' : GenerateArgNames(args_mod_in) , 'wrapped_class' : wrapper.wrapped_class_identifier() } ) ) answer.append( '}' ) cls.add_wrapper_code( os.linesep.join( answer ) ) # Add default body cls.add_wrapper_code( wrapper.create_default_function() ) # Add registration code reg = calldef.mem_fun_v_t( declaration, wrapper ) # WTF, why does it needs to be a code_creator instance. It only uses it for full_name cc = hackcodecreator_t(cls_name+'_wrapper') wrapper.parent = cc cls.add_registration_code( reg._create_impl(), True )
def is_setter( self, mem_fun ): # print "IN IS_SETTER", mem_fun if len( mem_fun.arguments ) != 1: return False if not declarations.is_void( mem_fun.return_type ): return False if mem_fun.has_const: return False # print "RETURNING TRUE" return True
def wrapper_return_type( self ): return_vars_count = len( self.return_variables ) if not declarations.is_void( self.function.return_type ): return_vars_count += 1 if 0 == return_vars_count: return self.function.return_type #return type is void elif 1 == return_vars_count: return declarations.dummy_type_t( 'boost::python::object' ) else: return declarations.dummy_type_t( 'boost::python::tuple' )
def wrapper_return_type(self): return_vars_count = len(self.return_variables) if not declarations.is_void(self.function.return_type): return_vars_count += 1 if 0 == return_vars_count: return self.function.return_type #return type is void elif 1 == return_vars_count: return declarations.dummy_type_t('boost::python::object') else: return declarations.dummy_type_t('boost::python::tuple')
def is_setter( self, mem_fun ): if len( mem_fun.arguments ) != 1: return False if not declarations.is_void( mem_fun.return_type ): return False if mem_fun.has_const: return False if mem_fun.overloads: return False return True
def is_setter(self, mem_fun): if len(mem_fun.arguments) != 1: return False if not declarations.is_void(mem_fun.return_type): return False if mem_fun.has_const: return False if mem_fun.overloads: return False return True
def create_fun_definition(self): cntrl = self.controller make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object') make_tuple = algorithm.create_identifier(self, 'boost::python::make_tuple') tmpl_values = dict() tmpl_values['unique_function_name'] = self.wrapper_name() tmpl_values[ 'return_type'] = self.controller.wrapper_return_type.decl_string tmpl_values['arg_declarations'] = self.args_declaration() tmpl_values['declare_variables'] \ = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) , cntrl.variables ) ) tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join(cntrl.pre_call)) tmpl_values['save_result'] = '' if not declarations.is_void(self.declaration.return_type): tmpl_tmp = '%(type)s %(name)s = ' if declarations.is_reference(self.declaration.return_type): tmpl_tmp = tmpl_tmp + '&' tmpl_values['save_result'] = tmpl_tmp \ % { 'type': cntrl.result_variable.type.decl_string , 'name' : cntrl.result_variable.name } tmpl_values['function_name'] = self.resolve_function_ref() tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions) return_stmt_creator = calldef_utils.return_stmt_creator_t( self, self.controller, self.controller.result_variable, self.controller.return_variables) tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join(cntrl.post_call)) if return_stmt_creator.pre_return_code: tmpl_values['post_call'] \ = os.linesep.join([ tmpl_values['post_call'] , self.indent( return_stmt_creator.pre_return_code )]) tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement) f_def = self.controller.template.substitute(tmpl_values) return remove_duplicate_linesep(f_def)
def pre_return_code(self): if None is self.__pre_return_code: if declarations.is_void( self.__function.return_type ) \ and ( self.__function.call_policies.is_default() \ or False == bool( self.__controller.return_variables ) ): self.__pre_return_code = '' elif self.__function.call_policies.is_default(): self.__pre_return_code = '' else: c_p_typedef = 'typedef %s %s;' \ % ( self.__function.call_policies.create_template_arg( self.__creator ) , self.__call_policy_alias ) self.__pre_return_code = c_p_typedef return self.__pre_return_code
def pre_return_code( self ): if None is self.__pre_return_code: if declarations.is_void( self.__function.return_type ) \ and ( self.__function.call_policies.is_default() \ or False == bool( self.__controller.return_variables ) ): self.__pre_return_code = '' elif self.__function.call_policies.is_default(): self.__pre_return_code = '' else: c_p_typedef = 'typedef %s %s;' \ % ( self.__function.call_policies.create_template_arg( self.__creator ) , self.__call_policy_alias ) self.__pre_return_code = c_p_typedef return self.__pre_return_code
def create_override(self): cntrl = self.controller.override_controller tmpl_values = dict() tmpl_values['return_type'] = self.declaration.return_type.decl_string tmpl_values['function_name'] = self.declaration.name tmpl_values['arg_declarations'] = self.args_override_declaration() tmpl_values['constness'] = '' if self.declaration.has_const: tmpl_values['constness'] = ' const ' tmpl_values['throw'] = self.throw_specifier_code() tmpl_values['py_function_var'] = cntrl.py_function_var tmpl_values['function_alias'] = self.declaration.alias tmpl_values['declare_py_variables'] \ = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string(), 2 ) , cntrl.py_variables ) ) tmpl_values['py_pre_call'] = os.linesep + self.indent( os.linesep.join(cntrl.py_pre_call), 2) tmpl_values['py_post_call'] = os.linesep + self.indent( os.linesep.join(cntrl.py_post_call), 2) tmpl_values['py_arg_expressions'] = '' if cntrl.py_arg_expressions: tmpl_values['py_arg_expressions'] \ = ', ' + self.PARAM_SEPARATOR.join( cntrl.py_arg_expressions ) tmpl_values[ 'save_py_result'] = "bpl::object %s = " % cntrl.py_result_variable.name tmpl_values['py_return'] = '' tmpl_values['cpp_return'] = '' if not declarations.is_void(self.declaration.return_type): tmpl_values['py_return'] \ = 'return bpl::extract< %(type)s >( pyplus_conv::get_out_argument( %(py_result)s, 0 ) );' \ % { 'type' : self.declaration.return_type.decl_string , 'py_result' : cntrl.py_result_variable.name } tmpl_values['cpp_return'] = 'return ' tmpl_values['wrapped_class'] = self.wrapped_class_identifier() arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator(self), self.declaration.arguments) tmpl_values['cpp_arg_expressions'] = arg_utils.call_args() f_def_code = cntrl.template.substitute(tmpl_values) return remove_duplicate_linesep(f_def_code)
def create_fun_definition(self): cntrl = self.controller make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) tmpl_values = dict() tmpl_values['unique_function_name'] = self.wrapper_name() tmpl_values['return_type'] = self.controller.wrapper_return_type.decl_string tmpl_values['arg_declarations'] = self.args_declaration() tmpl_values['declare_variables'] \ = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) , cntrl.variables ) ) tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) tmpl_values['save_result'] = '' if not declarations.is_void( self.declaration.return_type ): tmpl_tmp = '%(type)s %(name)s = ' if declarations.is_reference( self.declaration.return_type ): tmpl_tmp = tmpl_tmp + '&' tmpl_values['save_result'] = tmpl_tmp \ % { 'type': cntrl.result_variable.type.decl_string , 'name' : cntrl.result_variable.name } tmpl_values['function_name'] = self.resolve_function_ref() tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) return_stmt_creator = calldef_utils.return_stmt_creator_t( self , self.controller , self.controller.result_variable , self.controller.return_variables ) tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) if return_stmt_creator.pre_return_code: tmpl_values['post_call'] \ = os.linesep.join([ tmpl_values['post_call'] , self.indent( return_stmt_creator.pre_return_code )]) tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) f_def = self.controller.template.substitute(tmpl_values) return remove_duplicate_linesep( f_def )
def create_override(self): cntrl = self.controller.override_controller tmpl_values = dict() tmpl_values['return_type' ] = self.declaration.return_type.decl_string tmpl_values['function_name'] = self.declaration.name tmpl_values['arg_declarations'] = self.args_override_declaration() tmpl_values['constness'] = '' if self.declaration.has_const: tmpl_values['constness'] = ' const ' tmpl_values['throw'] = self.throw_specifier_code() tmpl_values['py_function_var'] = cntrl.py_function_var tmpl_values['function_alias'] = self.declaration.alias tmpl_values['declare_py_variables'] \ = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string(), 2 ) , cntrl.py_variables ) ) tmpl_values['py_pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_pre_call ), 2 ) tmpl_values['py_post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_post_call ), 2 ) tmpl_values['py_arg_expressions'] = '' if cntrl.py_arg_expressions: tmpl_values['py_arg_expressions'] \ = ', ' + self.PARAM_SEPARATOR.join( cntrl.py_arg_expressions ) tmpl_values['save_py_result'] = "bpl::object %s = " % cntrl.py_result_variable.name tmpl_values['py_return'] = '' tmpl_values['cpp_return'] = '' if not declarations.is_void( self.declaration.return_type ): tmpl_values['py_return'] \ = 'return bpl::extract< %(type)s >( pyplus_conv::get_out_argument( %(py_result)s, 0 ) );' \ % { 'type' : self.declaration.return_type.decl_string , 'py_result' : cntrl.py_result_variable.name } tmpl_values['cpp_return'] = 'return ' tmpl_values['wrapped_class'] = self.wrapped_class_identifier() arg_utils = calldef_utils.argument_utils_t( self.declaration , algorithm.make_id_creator( self ) , self.declaration.arguments ) tmpl_values['cpp_arg_expressions'] = arg_utils.call_args() f_def_code = cntrl.template.substitute(tmpl_values) return remove_duplicate_linesep( f_def_code )
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 restype_code(self): if not declarations.is_void( self.ftype.return_type ): return ctypes_formatter.as_ctype( self.ftype.return_type, self.top_parent.treat_char_ptr_as_binary_data ) else: return ''
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, "...")
def generate_code(): messages.disable( # Warnings 1020 - 1031 are all about why Py++ generates wrapper for class X messages.W1020 , messages.W1021 , messages.W1022 , messages.W1023 , messages.W1024 , messages.W1025 , messages.W1026 , messages.W1027 , messages.W1028 , messages.W1029 , messages.W1030 , messages.W1031 # , messages.W1035 # , messages.W1040 # , messages.W1038 # , messages.W1041 , messages.W1036 # pointer to Python immutable member , messages.W1033 # unnamed variables , messages.W1018 # expose unnamed classes , messages.W1049 # returns reference to local variable , messages.W1014 # unsupported '=' operator ) # # Use GCCXML to create the controlling XML file. # If the cache file (../cache/*.xml) doesn't exist it gets created, otherwise it just gets loaded # NOTE: If you update the source library code you need to manually delete the cache .XML file # xml_cached_fc = parser.create_cached_source_fc( os.path.join( environment.bullet.root_dir, "python_bullet.h" ) , environment.bullet.cache_file ) defined_symbols = [ 'BULLET_EXPORTS', '__GCCXML__', '_MSC_VER', '__MINGW32__' # needed to turn off allocator allignment which boost can't do.. ] defined_symbols.append( 'VERSION_' + environment.bullet.version ) if sys.platform.startswith ( 'linux' ): defined_symbols.append('USE_PTHREADS') # # build the core Py++ system from the GCCXML created source # mb = module_builder.module_builder_t( [ xml_cached_fc ] , gccxml_path=environment.gccxml_bin , working_directory=environment.root_dir , include_paths=environment.bullet.include_dirs , define_symbols=defined_symbols , indexing_suite_version=2 , cflags=environment.bullet.cflags ) # if this module depends on another set it here ## mb.register_module_dependency ( environment.ogre.generated_dir ) # normally implicit conversions work OK, however they can cause strange things to happen so safer to leave off mb.constructors().allow_implicit_conversion = False mb.BOOST_PYTHON_MAX_ARITY = 25 mb.classes().always_expose_using_scope = True # # We filter (both include and exclude) specific classes and functions that we want to wrap # global_ns = mb.global_ns global_ns.exclude() if MAIN_NAMESPACE == "" : main_ns = global_ns main_ns.include() else: main_ns = global_ns.namespace( MAIN_NAMESPACE ) main_ns.exclude () AutoInclude ( mb, MAIN_NAMESPACE ) ## note we use our own version, not common_utils common_utils.AutoExclude ( mb, MAIN_NAMESPACE ) ManualInclude ( mb ) # here we fixup functions that expect to modifiy their 'passed' variables ManualTransformations ( mb ) AutoFixes ( mb, MAIN_NAMESPACE ) # # We need to tell boost how to handle calling (and returning from) certain functions # Do this earlier than normal as I need to override the default in ManualFixes common_utils.Set_DefaultCall_Policies ( main_ns ) ManualFixes ( mb ) ManualExclude ( mb ) common_utils.Auto_Functional_Transformation ( main_ns ,special_vars=['btScalar *'] ) # # the manual stuff all done here !!! # hand_made_wrappers.apply( mb ) NoPropClasses = [""] for cls in main_ns.classes(): if cls.name not in NoPropClasses: rec = ogre_properties.ogre_property_recognizer_t() rec.addSetterType ( 'btScalar' ) # this type is a 'float/double' however we need to tell py++ such so it creates setters cls.add_properties( recognizer=rec ) common_utils.Auto_Document( mb, MAIN_NAMESPACE ) ## add additional version information to the module to help identify it correctly common_utils.addDetailVersion ( mb, environment, environment.bullet ) mem_fun = main_ns.member_function('::btVector3::setX') ##print "setter:", property_recognizer_i (mem_fun) if len( mem_fun.arguments ) != 1: print 'False1' if not declarations.is_void( mem_fun.return_type ): print 'False2' if mem_fun.has_const: print 'False3' if mem_fun.overloads: print 'False4' print "OK" ########################################################################################## # # Creating the code. After this step you should not modify/customize declarations. # ########################################################################################## # # extractor = exdoc.doc_extractor( "Ogre" ) # # mb.build_code_creator (module_name='_ogre_' , doc_extractor= extractor ) extractor = exdoc.doc_extractor() # I'm excluding the UTFstring docs as lots about nothing mb.build_code_creator (module_name='_bullet_' , doc_extractor= extractor ) for inc in environment.bullet.include_dirs: mb.code_creator.user_defined_directories.append(inc ) mb.code_creator.user_defined_directories.append( environment.bullet.generated_dir ) mb.code_creator.replace_included_headers( customization_data.header_files( environment.bullet.version ) ) huge_classes = map( mb.class_, customization_data.huge_classes( environment.bullet.version ) ) mb.split_module(environment.bullet.generated_dir, huge_classes, use_files_sum_repository=False) ## now we need to ensure a series of headers and additional source files are ## copied to the generaated directory.. additional_files=[ os.path.join( os.path.abspath(os.path.dirname(__file__) ), 'python_bullet_masterlist.h' ) ] if environment.isLinux(): #sBulletDNAlen is defined in the cpp file not the header!! additional_files.append ( os.path.join( environment.Config.PATH_Bullet, 'src', 'LinearMath','btSerializer.cpp' ) ) for sourcefile in additional_files: p,filename = os.path.split(sourcefile) destfile = os.path.join(environment.bullet.generated_dir, filename ) if not common_utils.samefile( sourcefile ,destfile ): shutil.copy( sourcefile, environment.bullet.generated_dir ) print "Updated ", filename, "as it was missing or out of date"