def is_supported(oper): """returns True if Boost.Python support the operator""" if oper.symbol == "*" and len(oper.arguments) == 0: # dereference does not make sense return False if oper.symbol != "<<": return oper.symbol in operators_helper.all args_len = len(oper.arguments) if isinstance(oper, declarations.member_operator_t): # and args_len != 1: return False # Boost.Python does not support member operator<< :-( if isinstance(oper, declarations.free_operator_t) and args_len != 2: return False if not declarations.is_same(oper.return_type, oper.arguments[0].type): return False type_ = oper.return_type if not declarations.is_reference(type_): return False type_ = declarations.remove_reference(type_) if declarations.is_const(type_): return False if args_len == 2: # second argument should has "T const &" type, otherwise the code will not compile tmp = oper.arguments[1].type if not declarations.is_reference(tmp): return False tmp = declarations.remove_reference(tmp) if not declarations.is_const(tmp): return False return declarations.is_std_ostream(type_) or declarations.is_std_wostream(type_)
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 AutoExclude( mb ): """ Automaticaly exclude a range of things that don't convert well from C++ to Python """ global_ns = mb.global_ns for ns in NAMESPACES: main_ns = global_ns.namespace( ns ) # vars that are static consts but have their values set in the header file are bad Remove_Static_Consts ( main_ns ) ## Exclude protected and private that are not pure virtual query = declarations.access_type_matcher_t( 'private' ) \ & ~declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.PURE_VIRTUAL ) try: non_public_non_pure_virtual = main_ns.calldefs( query ) non_public_non_pure_virtual.exclude() except: pass #Virtual functions that return reference could not be overriden from Python query = declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.VIRTUAL ) \ & declarations.custom_matcher_t( lambda decl: declarations.is_reference( decl.return_type ) ) try: main_ns.calldefs( query ).virtuality = declarations.VIRTUALITY_TYPES.NOT_VIRTUAL except: pass
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 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 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 test( self ): buggy = self.global_ns.mem_fun( 'buggy' ) ExpressionError = self.global_ns.class_( 'ExpressionError' ) self.failUnless( len( buggy.exceptions ) == 1 ) err = buggy.exceptions[0] self.failUnless( declarations.is_reference( err ) ) err = declarations.remove_declarated( declarations.remove_reference( err ) ) self.failUnless( err is ExpressionError )
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 test(self): buggy = self.global_ns.member_function('buggy') expression_error = self.global_ns.class_('ExpressionError') self.assertTrue(len(buggy.exceptions) == 1) err = buggy.exceptions[0] self.assertTrue(declarations.is_reference(err)) err = declarations.remove_declarated( declarations.remove_reference(err)) self.assertTrue(err is expression_error)
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 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 get_overridable( self ): """Check if the method can be overridden.""" if None is self._overridable: if isinstance( self, declarations.member_calldef_t ) \ and self.virtuality != declarations.VIRTUALITY_TYPES.NOT_VIRTUAL \ and declarations.is_reference( self.return_type ): self._overridable = False self._non_overridable_reason = messages.W1049 else: self._overridable = True self._non_overridable_reason = "" return self._overridable
def AutoExclude( mb ): """ Automaticaly exclude a range of things that don't convert well from C++ to Python """ global_ns = mb.global_ns main_ns = global_ns # No namespaces in NxPhysics #Virtual functions that return reference could not be overriden from Python query = declarations.virtuality_type_matcher_t( declarations.VIRTUALITY_TYPES.VIRTUAL ) \ & declarations.custom_matcher_t( lambda decl: declarations.is_reference( decl.return_type ) ) try: main_ns.calldefs( query ).virtuality = declarations.VIRTUALITY_TYPES.NOT_VIRTUAL except: pass
def create_holder( self, class_decl ): #holder should be created when we pass object created in python #as parameter to function in C++ that takes the smart pointer by reference found = self._find_smart_ptrs( self.__arguments_types, class_decl ) if not found: return None#not found or ambiguty held_type = None for smart_ptr, type_ in found: if declarations.is_reference( type_ ) and not declarations.is_const( type_.base ): temp = code_creators.held_type_t( smart_ptr=smart_ptr ) if not held_type or 'shared_ptr' in smart_ptr: held_type = temp return held_type
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 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 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 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 visit_casting_operator( self ): self.__dependencies_manager.add_exported( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.__types_db.update( self.curr_decl ) if not self.curr_decl.parent.is_abstract and not declarations.is_reference( self.curr_decl.return_type ): maker = code_creators.casting_operator_t( operator=self.curr_decl ) self.__module_body.adopt_creator( maker ) self.__opaque_types_manager.register_opaque( maker, self.curr_decl ) #what to do if class is abstract maker = code_creators.casting_member_operator_t( operator=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) self.__opaque_types_manager.register_opaque( maker, self.curr_decl )
def check_type_compatibility(self, fget, fset): if decl_wrappers.name_based_recognizer_t.check_type_compatibility(self, fget, fset): return True # N.B.: la base non contempla il caso il cui la get restituisca "type" e la set abbia come parametro "const type &" (capita ad esempio in circostanze dove il valore di ritorno della get viene ottenuto tramite conversione da stringa) t1 = fget.return_type t2 = fset.arguments[0].type if declarations.is_reference(t2): t2 = declarations.remove_cv( declarations.remove_reference( t2 ) ) if declarations.is_same( t1, t2 ): return True 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 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 ): controller_base_t.__init__( self, function ) self.__vars_manager = create_variables_manager( function ) self.__wrapper_args = [ arg.clone() for arg in function.arguments ] initialize_expr = '' result_type = self.function.return_type if declarations.is_reference( self.function.return_type ): initialize_expr = ' = 0' result_type = declarations.pointer_t( declarations.remove_reference( self.function.return_type ) ) self.__result_var = variable_t( result_type , self.register_variable_name( 'result' ) , initialize_expr=initialize_expr ) self.__return_variables = [] self.__pre_call = [] self.__post_call = [] self.__arg_expressions = [ arg.name for arg in function.arguments ]
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 visit_casting_operator(self): self.__dependencies_manager.add_exported(self.curr_decl) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl) self.__types_db.update(self.curr_decl) if not self.curr_decl.parent.is_abstract and not declarations.is_reference( self.curr_decl.return_type): maker = code_creators.casting_operator_t(operator=self.curr_decl) self.__module_body.adopt_creator(maker) self.__opaque_types_manager.register_opaque(maker, self.curr_decl) #what to do if class is abstract maker = code_creators.casting_member_operator_t( operator=self.curr_decl) self.curr_code_creator.adopt_creator(maker) self.__opaque_types_manager.register_opaque(maker, self.curr_decl)
def __init__(self, function): controller_base_t.__init__(self, function) self.__vars_manager = create_variables_manager(function) self.__wrapper_args = [arg.clone() for arg in function.arguments] initialize_expr = '' result_type = self.function.return_type if declarations.is_reference(self.function.return_type): initialize_expr = ' = 0' result_type = declarations.pointer_t( declarations.remove_reference(self.function.return_type)) self.__result_var = variable_t(result_type, self.register_variable_name('result'), initialize_expr=initialize_expr) self.__return_variables = [] self.__pre_call = [] self.__post_call = [] self.__arg_expressions = [arg.name for arg in function.arguments]
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 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 visit_variable(self): self.__types_db.update( self.curr_decl ) self.__dependencies_manager.add_exported( self.curr_decl ) 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 __call__(self, variable, hint=None): if not isinstance(variable, declarations.variable_t): return None assert hint in ('get', 'set') if not declarations.is_reference(variable.decl_type): return None no_ref = declarations.remove_reference(variable.decl_type) base_type = declarations.remove_const(no_ref) if python_traits.is_immutable(base_type): #the relevant code creator will generate code, that will return this member variable #by value return decl_wrappers.default_call_policies() if not isinstance(base_type, declarations.declarated_t): return None base_type = declarations.remove_alias(base_type) declaration = base_type.declaration if declarations.is_class_declaration(declaration): return None if declaration.is_abstract: return None if declarations.has_destructor( declaration ) and not declarations.has_public_destructor(declaration): return None if not declarations.has_copy_constructor(declaration): return None if hint == 'get': #if we rich this line, it means that we are able to create an obect using #copy constructor. if declarations.is_const(no_ref): return decl_wrappers.return_value_policy( decl_wrappers.copy_const_reference) else: return decl_wrappers.return_value_policy( decl_wrappers.copy_non_const_reference) else: return decl_wrappers.default_call_policies()
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( [self.indent( var.declare_var_string() ) for var in 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 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 __call__(self, calldef, hint=None): if not isinstance( calldef, declarations.calldef_t ): return None if not isinstance( calldef, declarations.member_operator_t ): return None if calldef.symbol != '[]': return None return_type = declarations.remove_cv( calldef.return_type ) if declarations.is_reference( return_type ): return_type = declarations.remove_reference( return_type ) if python_traits.is_immutable( return_type ): if declarations.is_const( calldef.return_type ): return decl_wrappers.return_value_policy( decl_wrappers.copy_const_reference ) else: return decl_wrappers.return_value_policy( decl_wrappers.copy_non_const_reference ) else: return decl_wrappers.return_internal_reference()
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 """ ode_ns = mb.global_ns ### Again, no sperate namespace .namespace ('ode') mem_funs = ode_ns.calldefs () mem_funs.create_with_signature = True #Generated code will not compile on #MSVC 7.1 if function has throw modifier. resolver = call_policies_resolver.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 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( '::boost::python::return_pointee_value' )
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 __call__( self, variable, hint=None ): if not isinstance( variable, declarations.variable_t ): return None assert hint in ( 'get', 'set' ) if not declarations.is_reference( variable.type ): return None no_ref = declarations.remove_reference( variable.type ) base_type = declarations.remove_const( no_ref ) if python_traits.is_immutable( base_type ): #the relevant code creator will generate code, that will return this member variable #by value return decl_wrappers.default_call_policies() if not isinstance( base_type, declarations.declarated_t ): return None base_type = declarations.remove_alias( base_type ) decl = base_type.declaration if declarations.is_class_declaration( decl ): return None if decl.is_abstract: return None if declarations.has_destructor( decl ) and not declarations.has_public_destructor( decl ): return None if not declarations.has_copy_constructor(decl): return None if hint == 'get': #if we rich this line, it means that we are able to create an obect using #copy constructor. if declarations.is_const( no_ref ): return decl_wrappers.return_value_policy( decl_wrappers.copy_const_reference ) else: return decl_wrappers.return_value_policy( decl_wrappers.copy_non_const_reference ) else: return decl_wrappers.default_call_policies()
def set_call_policies( mb ): CEGUI_ns = mb.global_ns.namespace ('CEGUI') # Set the default policy to deal with pointer/reference return types to reference_existing object # as this is the CEGUI Default. mem_funs = CEGUI_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 ) ## OK so the CEGUI String class is ugly (from a python perspective) ## I'm going to fix the pointer arguments so you can use ctypes to use the class ## however real work is in hand_made_wrappers with a new 'assign' function for fun in CEGUI_ns.class_('String').member_functions(): arg_position = 0 for arg in fun.arguments: if declarations.type_traits.is_pointer(arg.type): # fun.add_transformation( ft.modify_type(arg_position,common_utils._ReturnUnsignedInt ), alias=fun.name ) fun.documentation = common_utils.docit ("Modified Input Argument to work with CTypes", "Argument "+arg.name+ "(pos:" + str(arg_position)\ +") takes a CTypes.adddressof(xx)", "...") break arg_position +=1 for fun in CEGUI_ns.class_('String').constructors(): arg_position = 0 for arg in fun.arguments: if declarations.type_traits.is_pointer(arg.type): fun.add_transformation( ft.modify_type(arg_position,common_utils._ReturnUnsignedInt ), alias=fun.name ) fun.documentation = common_utils.docit ("Modified Input Argument to work with CTypes", "Argument "+arg.name+ "(pos:" + str(arg_position)\ +") takes a CTypes.adddressof(xx)", "...") break arg_position +=1
def __find_out_is_read_only(self): type_ = declarations.remove_alias( self.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 __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 add_autowrap_classes_to_builder(builder, component_name, classes): # Convience dict for call policies call_policies_collection = { "reference_existing_object": call_policies.return_value_policy( call_policies.reference_existing_object), "return_opaque_pointer": call_policies.return_value_policy(call_policies.return_opaque_pointer), "return_internal_reference": call_policies.return_internal_reference(), "copy_const_reference": call_policies.return_value_policy(call_policies.copy_const_reference) } # Classes which have methods taking or returning PETSc vec or mat need to add # this custom wrapper code to allow wrapping of PETSc opaque pointers. Any # methods returning them also needs to set up opaque pointer management by # choosing the Py++ 'return_opaque_pointer' option. petsc_mat_custom_code = "BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID( _p_Mat )" petsc_vec_custom_code = "BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID( _p_Vec )" # Remove any classes not in this module. Also use the class to collect cell and population writers. cell_writers = [] population_writers = [] classes_not_in_module = [] for eachClass in classes: # Collect writers if eachClass.full_path is not None: if "/cell_based/src/writers/cell_writers/" in eachClass.full_path: if "Abstract" not in eachClass.name: cell_writers.append(eachClass.name) if "/cell_based/src/writers/population_writers/" in eachClass.full_path: if "Abstract" not in eachClass.name: population_writers.append(eachClass.name) if not eachClass.needs_auto_wrapper_generation(): continue if eachClass.component != component_name: full_class_names = eachClass.get_full_names() for eachTemplatedClassName in full_class_names: classes_not_in_module.append( eachTemplatedClassName.replace(' ', '')) builder.classes(lambda decl: decl.name.replace(' ', '') in classes_not_in_module).exclude() # Exclude all iterators builder.classes(lambda x: x.name in ("Iterator", )).exclude() # Set up the class in the Py++ builder for eachClass in classes: if not eachClass.needs_auto_wrapper_generation(): continue if eachClass.component == component_name: short_class_names = eachClass.get_short_names() full_class_names = eachClass.get_full_names() for idx, eachTemplatedClassName in enumerate(full_class_names): # Add the class to the builder print "Processing: ", eachTemplatedClassName, " aka ", short_class_names[ idx] this_class = builder.class_(eachTemplatedClassName) this_class.include() # Rename the class with its short name, avoids having complicated # class names, which Py++ would have to deal with, in the C++ wrapper code. if (short_class_names[idx] != eachTemplatedClassName): this_class.rename(short_class_names[idx]) # Set up member function excludes and pointer management has_members = False try: this_class.member_functions() has_members = True except RuntimeError: pass has_constructors = False try: this_class.constructors() has_constructors = True except RuntimeError: pass add_petsc_vec_code = False add_petsc_mat_code = False petsc_vec_code_will_auto = False petsc_mat_code_will_auto = False if has_constructors: for eachConstructor in this_class.constructors(): for eachArgType in eachConstructor.arguments: declaration_string = eachArgType.decl_type.decl_string default_value = eachArgType.default_value if "Vec" in declaration_string and not "CellVecData" in declaration_string: add_petsc_vec_code = True if "Mat" in declaration_string: add_petsc_mat_code = True # Workaround for Bug with default arguments and templates. # Assume the template value in the argument is the same as # in the default. if default_value is not None: if "DIM" in default_value: print "INFO: Found method default arguement with incomplete type. Guessing the type." if "3" in declaration_string: eachArgType.default_value = default_value.replace( "DIM", str(3)) if "2" in declaration_string: eachArgType.default_value = default_value.replace( "DIM", str(2)) if has_members: for eachMemberFunction in this_class.member_functions(): # Exclude any specified member functions if eachClass.excluded_methods is not None and eachMemberFunction.name in eachClass.excluded_methods: eachMemberFunction.exclude() continue # PETSc Vec and Mat args need special care for eachArgType in eachMemberFunction.arguments: declaration_string = eachArgType.decl_type.decl_string default_value = eachArgType.default_value if default_value is not None and "nullptr" in default_value: eachArgType.default_value = default_value.replace( "nullptr", "NULL") #pprint (vars(eachArgType)) if "Vec" in declaration_string and not "CellVecData" in declaration_string: add_petsc_vec_code = True if "Mat" in declaration_string: add_petsc_mat_code = True # Bug with default arguments and templates if eachArgType.default_value is not None: if "DIM" in eachArgType.default_value: print "INFO: Found method default arguement with incomplete type. Guessing the type." if "3" in declaration_string: eachArgType.default_value = default_value.replace( "DIM", str(3)) if "2" in declaration_string: eachArgType.default_value = default_value.replace( "DIM", str(2)) # If there are explicit call policies add them break_out = False if eachClass.pointer_return_methods is not None: for eachDefinedPointerPolicy in eachClass.pointer_return_methods: if eachMemberFunction.name == eachDefinedPointerPolicy[ 0]: if eachDefinedPointerPolicy[ 1] in call_policies_collection.keys( ): eachMemberFunction.call_policies = call_policies_collection[ eachDefinedPointerPolicy[1]] break_out = True break if break_out: continue # PETSc Vec and Mat need special care if "Vec" in str(eachMemberFunction.return_type ) and not "CellVecData" in str( eachMemberFunction.return_type): eachMemberFunction.call_policies = call_policies_collection[ "return_opaque_pointer"] petsc_vec_code_will_auto = True continue if "Mat" in str(eachMemberFunction.return_type): eachMemberFunction.call_policies = call_policies_collection[ "return_opaque_pointer"] petsc_mat_code_will_auto = True continue if declarations.is_pointer( eachMemberFunction.return_type): eachMemberFunction.call_policies = call_policies_collection[ "reference_existing_object"] continue if declarations.is_reference( eachMemberFunction.return_type): eachMemberFunction.call_policies = call_policies_collection[ "return_internal_reference"] continue # Explicitly remove abstract class constructors # if "Abstract" in eachClass.name: # this_class.constructors().exclude() # Set up variable excludes if eachClass.excluded_variables is not None: for eachVariable in eachClass.excluded_variables: this_class.variables(eachVariable).exclude() # Add declaration code if add_petsc_vec_code and not petsc_vec_code_will_auto: print "Petsc Vec found: Adding custom declaration code." this_class.add_declaration_code(petsc_vec_custom_code) if add_petsc_mat_code and not petsc_mat_code_will_auto: print "Petsc Mat found: Adding custom declaration code." this_class.add_declaration_code(petsc_mat_custom_code) if eachClass.declaration_code is not None: for eachLine in eachClass.declaration_code: this_class.add_declaration_code(eachLine) # If this is a suitable class (i.e. concentrete cell population) # add writer template functions. if eachClass.full_path is not None: if "/cell_based/src/population/" in eachClass.full_path: if "Abstract" not in eachClass.name and "CellwiseDataGradient" not in eachClass.name: if "BasedCellPopulation" in eachClass.name: for eachWriter in cell_writers: writer_prefix = 'def("AddCellWriter' + eachWriter + '", &' writer_suffix = '::AddCellWriter<' + eachWriter + '>)' this_class.add_registration_code( writer_prefix + eachTemplatedClassName + writer_suffix) for eachWriter in population_writers: writer_prefix = 'def("AddPopulationWriter' + eachWriter + '", &' writer_suffix = '::AddPopulationWriter<' + eachWriter + '>)' this_class.add_registration_code( writer_prefix + eachTemplatedClassName + writer_suffix) # Bug with null type in default template arguements for eachTemplate in ["<2>", "<3>"]: builder.class_("AbstractPdeModifier" + eachTemplate).constructors().exclude() builder.class_('AbstractPdeModifier' + eachTemplate).calldefs().use_default_arguments = False # Don't return non-const reference for ChastePoint returns_non_const_ref = builder.class_('ChastePoint<3>').member_functions( return_type="::boost::numeric::ublas::c_vector<double, 3> &") returns_non_const_ref.exclude() returns_non_const_ref = builder.class_('ChastePoint<2>').member_functions( return_type="::boost::numeric::ublas::c_vector<double, 2> &") returns_non_const_ref.exclude() return builder, classes
def generate(defined_symbols, extraIncludes): messages.disable( messages.W1005 # using a non public variable type for arguments or returns , messages.W1006 # `Py++` need your # help to expose function that takes > as argument/returns C++ arrays. # Take a look on "Function Transformation" > functionality and define # the transformation. , messages.W1007 # more than 10 args -> BOOST_PYTHON_MAX_ARITY is set , messages.W1009 # execution error W1009: The function takes as argument (name=pFunIdx, pos=1) > # non-const reference to Python immutable type - function could not be called > from Python , messages.W1014 # "operator*" is not supported. See , messages.W1016 # `Py++` does not exports non-const casting operators # Warnings 1020 - 1031 are all about why Py++ generates wrapper for class X , messages.W1023 # Py++` will generate class wrapper - there are few functions that should be # redefined in class wrapper , messages.W1025 # `Py++` will generate class wrapper - class contains "c_" - T* > member variable , messages.W1026 # `Py++` will generate class wrapper - class contains "arr_" - T& > member variable , messages.W1027 # `Py++` will generate class wrapper - class contains "mat_" - > array member variable , messages.W1035 # error. `Py++` can not expose static pointer member variables. , messages.W1036 # error. `Py++` can not expose pointer to Python immutable > member variables. This # could be changed in future. , messages.W1040 # error. The declaration is unexposed, but there are other > declarations, which # refer to it. This could cause "no to_python converter > found" run # time error # This is serious and lead to RuntimeError: `Py++` is going to write different content to the same file , messages.W1047 # There are two or more classes that use same > alias("MatElement"). Duplicated aliases causes # few problems, but the main one > is that some of the classes will not # be exposed to Python.Other classes : > , messages.W1049 # This method could not be overriden in Python - method returns > # reference to local variable! , messages.W1052 # `Py++` will not expose free operator ) logger.debug("Install SRC: ", os.path.abspath(__file__)) logger.debug("Execute from: ", os.getcwd()) sourcedir = os.path.dirname(os.path.abspath(__file__)) sourceHeader = os.path.abspath(sourcedir + "/" + r"pygimli.h") gimliInclude = os.path.dirname( os.path.abspath(sourcedir + "/../src/" + r"gimli.h")) settings.includesPaths.append(gimliInclude) xml_cached_fc = parser.create_cached_source_fc( sourceHeader, settings.module_name + '.cache') import platform defines = ['PYGIMLI_CAST', 'HAVE_BOOST_THREAD_HPP'] caster = 'gccxml' compiler_path = options.clang if platform.system() == 'Windows': if platform.architecture()[0] == '64bit': #compiler_path = 'C:/msys64/mingw64/bin/clang++' if sys.platform == 'darwin': pass else: defines.append('_WIN64') defines.append('MS_WIN64') logger.info('Marking win64 for gccxml') else: pass #compiler_path = 'C:/msys32/mingw32/bin/clang++' if len(compiler_path) == 0: compiler_path = None for define in [settings.gimli_defines, defined_symbols]: if len(define) > 0: defines.append(define) try: if sys.platform == 'win32': # os.name == 'nt' (default on my mingw)results in wrong commandline # for gccxml os.name = 'mingw' casterpath = settings.caster_path.replace('\\', '\\\\') casterpath = settings.caster_path.replace('/', '\\') if 'gccxml' not in casterpath: caster = 'castxml' if '.exe' not in casterpath: casterpath += '\\' + caster + '.exe' else: casterpath = settings.caster_path if 'gccxml' not in casterpath: caster = 'castxml' except Exception as e: logger.info("caster_path=%s" % casterpath) logger.info(str(e)) raise Exception("Problems determine castxml binary") settings.includesPaths.insert(0, os.path.abspath(extraIncludes)) logger.info("caster_path=%s" % casterpath) logger.info("working_directory=%s" % settings.gimli_path) logger.info("include_paths=%s" % settings.includesPaths) logger.info("define_symbols=%s" % defines) logger.info("compiler_path=%s" % compiler_path) logger.info("indexing_suite_version=2") xml_generator_config = parser.xml_generator_configuration_t( xml_generator=caster, xml_generator_path=casterpath, working_directory=settings.gimli_path, include_paths=settings.includesPaths, define_symbols=defines, ignore_gccxml_output=False, cflags="", compiler_path=compiler_path) mb = module_builder.module_builder_t( [xml_cached_fc], indexing_suite_version=2, xml_generator_config=xml_generator_config ) logger.info("Reading of c++ sources done.") mb.classes().always_expose_using_scope = True mb.calldefs().create_with_signature = True global_ns = mb.global_ns global_ns.exclude() main_ns = global_ns.namespace(MAIN_NAMESPACE) main_ns.include() # for c in main_ns.free_functions(): # print(c) # if 'pow' in c.name: # print(c) # print(c.name) # if c.decl_string.startswith('::GIMLI::pow'): # print(c) # print(c.name) # sys.exit() logger.info("Apply handmade wrappers.") try: hand_made_wrappers.apply(mb) except BaseException as e: print(e) logger.info("Apply custom rvalues.") # START manual r-value converters rvalue_converters = [ 'register_pytuple_to_rvector3_conversion', 'register_pysequence_to_rvector_conversion', # 'register_pysequence_to_bvector_conversion', 'register_pysequence_to_indexvector_conversion', 'register_pysequence_to_r3vector_conversion', 'register_pysequence_to_StdVectorRVector3_conversion', # 'register_rvector_to_ndarray_conversion', ] for converter in rvalue_converters: mb.add_declaration_code('void %s();' % converter) mb.add_registration_code('%s();' % converter) # END manual r-value converters custom_rvalue_path = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp') logger.info("Starting to exclude stuff that we don't need " "or that is known to be spurious.") exclude(main_ns.variables, name=[ 'Triangle6_S1', 'Triangle6_S2', 'Triangle6_S3', 'HexahedronFacesID', 'Hexahedron20FacesID', 'TetrahedronFacesID', 'HexahedronSplit5TetID', 'HexahedronSplit6TetID', 'TriPrismFacesID', 'TriPrimSplit3TetID', 'NodeCoordinates', 'EdgeCoordinates', 'TriCoordinates', 'QuadCoordinates', 'TetCoordinates', 'HexCoordinates', 'PrismCoordinates', 'PyramidCoordinates', 'PyramidFacesID', 'Tet10NodeSplit', 'Tet10NodeSplitZienk', 'Hex20NodeSplit', 'Prism15NodeSplit', 'Pyramid13NodeSplit' ] ) exclude(main_ns.free_functions, return_type=[ 'float *', 'float &', "::GIMLI::__VectorExpr< double, " + "GIMLI::__VectorUnaryExprOp< double, " + "GIMLI::VectorIterator< double >, GIMLI::ABS_ > >"], name=[ 'strReplaceBlankWithUnderscore', 'toStr', 'toInt', 'toFloat', 'toDouble', 'str', 'getRowSubstrings', 'getNonEmptyRow', 'getSubstrings', 'abs', 'type'] ) exclude(main_ns.free_operators, name=[''], return_type=['::std::ostream &', '::std::istream &'] ) exclude(main_ns.classes, name=['ABS_', 'ACOT', 'ATAN', 'COS', 'COT', 'EXP', 'ABS_', 'LOG', 'LOG10', 'SIGN', 'SIN', 'SQRT', 'SQR', 'TAN', 'TANH', 'PLUS', 'MINUS', 'MULT', 'DIVID', 'BINASSIGN', 'cerrPtr', 'cerrPtrObject', 'coutPtr', 'coutPtrObject', 'deletePtr', 'edge_', 'distancePair_', 'IPCMessage', 'PythonGILSave', ] ) exclude(main_ns.member_functions, name=['begin', 'end', 'val'], return_type=[''] ) exclude(main_ns.member_operators, symbol=['']) for f in main_ns.declarations: if isinstance(f, decl_wrappers.calldef_wrapper.free_function_t): if (str(f.return_type).find('GIMLI::VectorExpr') != -1): f.exclude() ex = ['::GIMLI::MatrixElement', '::GIMLI::__VectorUnaryExprOp', '::GIMLI::__VectorBinaryExprOp', '::GIMLI::__ValVectorExprOp', '::GIMLI::__VectorValExprOp', '::GIMLI::__VectorExpr', '::GIMLI::Expr', '::GIMLI::InversionBase', 'GIMLI::MatrixElement', 'GIMLI::__VectorUnaryExprOp', 'GIMLI::__VectorBinaryExprOp', 'GIMLI::__ValVectorExprOp', 'GIMLI::__VectorValExprOp', 'GIMLI::__VectorExpr', 'GIMLI::Expr', 'GIMLI::InversionBase', 'std::vector<unsigned long', 'std::vector<bool', 'std::vector<double', ] for c in main_ns.free_functions(): for e in ex: if c.decl_string.find(e) > -1: try: c.exclude() logger.debug("Exclude: " + str(c)) except BaseException as _: logger.debug("Fail to exclude: " + str(c)) for c in main_ns.classes(): for e in ex: if c.decl_string.startswith(e): try: c.exclude() logger.debug("Exclude: " + c.name) except BaseException as _: logger.debug("Fail to exclude: " + c.name) try: for mem in c.variables(): try: mem.exclude() # logger.info("Exclude: " + str(mem)) except BaseException as _: logger.debug("Fail to exclude: " + str(mem)) except BaseException as _: # print(c, "has no member functions") pass try: for mem in c.constructors(): for e in ex: if mem.decl_string.find(e) > -1: try: mem.exclude() # logger.info("Exclude: " + str(mem)) except BaseException as _: logger.debug("Fail to exclude: " + str(mem)) for mem in c.member_functions(): for e in ex: if mem.decl_string.find(e) > -1: try: mem.exclude() # logger.info("Exclude: " + str(mem)) except BaseException as _: logger.debug("Fail to exclude: " + str(mem)) except BaseException as _: # print(c, "has no member functions") pass # print('#'*100) # print(c, c.name) if c.name.startswith('Vector<unsigned long>'): # print(' ', c.name) for mem in c.constructors(): # print("mem", mem, mem.decl_string) if mem.decl_string.find('( ::GIMLI::Index )') > -1: logger.debug("Exclude: " + str(mem)) mem.exclude() # print("mem", mem) try: mb.calldefs(access_type_matcher_t('protected')).exclude() mb.calldefs(access_type_matcher_t('private')).exclude() except BaseException as _: pass # setMemberFunctionCallPolicieByReturn(mb, [ '::GIMLI::Node &' # , '::GIMLI::Cell &' # , '::GIMLI::Boundary &' # , '::GIMLI::Shape &' # , '::GIMLI::Node *' # , '::GIMLI::Cell *' # , '::GIMLI::Boundary *' # , '::GIMLI::Shape *' # ] # , call_policies.reference_existing_object) setMemberFunctionCallPolicieByReturn( mb, ['::std::string *', 'float *', 'double *', 'int *', 'long *', 'long int *', 'long long int *', 'unsigned int *', 'long unsigned int *', 'unsigned long long int *', 'long long unsigned int *', '::GIMLI::Index *', '::GIMLI::SIndex *', 'bool *'], call_policies.return_pointee_value) setMemberFunctionCallPolicieByReturn(mb, ['::std::string &', 'float &', 'double &', 'int &', 'long &', 'long int &', 'long long int &', 'unsigned int &', 'long unsigned int &', 'long long unsigned int &', 'unsigned long long int &', '::GIMLI::Index &', '::GIMLI::SIndex &', 'bool &' ], call_policies.return_by_value) # setMemberFunctionCallPolicieByReturn(mb, # ['::GIMLI::VectorIterator<double> &'] # , call_policies.copy_const_reference) # setMemberFunctionCallPolicieByReturn(mb, [ # , 'double &' ] # , call_policies.reference_existing_object) # call_policies.return_value_policy(call_policies.reference_existing_object) # call_policies.return_value_policy(call_policies.copy_non_const_reference) # call_policies.return_value_policy(call_policies.copy_const_reference) # addAutoConversions(mb) # excludeMemberByReturn(main_ns, ['::DCFEMLib::SparseMatrix<double> &']) # fun = mb.global_ns.member_functions('begin', allow_empty=True) # for f in fun: # f.exclude() # excludeFreeFunctionsByName(main_ns, ['strReplaceBlankWithUnderscore' # 'toStr', 'toInt', 'toFloat', 'toDouble', # 'getRowSubstrings', 'getNonEmptyRow', 'getSubstrings' ]) # excludeFreeFunctionsByReturn(main_ns, [ 'float *', 'float &' ]) # fun = ns.free_operators(return_type=funct, allow_empty=True) # excludeMemberOperators(main_ns, ['++', '--', '*']) # exclude all that does not match any predefined callpolicie excludeRest = True if excludeRest: mem_funs = mb.calldefs() 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)): # print mem_fun # mem_fun.exclude() mem_fun.call_policies = call_policies.return_value_policy( call_policies.reference_existing_object) # mem_fun.call_policies = \ # call_policies.return_value_policy(call_policies.return_pointee_value) # mem_fun.call_policies = \ # call_policies.return_value_policy(call_policies.return_opaque_pointer) # mem_fun.call_policies = \ # call_policies.return_value_policy(call_policies.copy_non_const_reference) logger.info("Create api documentation from Doxgen comments.") # Now it is the time to give a name to our module from doxygen import doxygen_doc_extractor extractor = doxygen_doc_extractor() logger.info("Create code creator.") mb.build_code_creator(settings.module_name, doc_extractor=extractor) # It is common requirement in software world-each file should have license # mb.code_creator.license = '//Boost Software # License(http://boost.org/more/license_info.html)' # I don't want absolute includes within code mb.code_creator.user_defined_directories.append(os.path.abspath('.')) # And finally we can write code to the disk def ignore(val): pass logger.info("Create bindings code.") mb.split_module('./generated', on_unused_file_found=ignore) additional_files = [ os.path.join( os.path.abspath(os.path.dirname(__file__)), 'custom_rvalue.cpp'), os.path.join( os.path.abspath(os.path.dirname(__file__)), 'generators.h'), os.path.join( os.path.abspath(os.path.dirname(__file__)), 'tuples.hpp')] logger.info("Add additional files.") for sourcefile in additional_files: p, filename = os.path.split(sourcefile) destfile = os.path.join('./generated', filename) if not samefile(sourcefile, destfile): shutil.copy(sourcefile, './generated') logger.info("Updated " + filename + "as it was missing or out of date")
# Find out the file location within the sources tree this_module_dir_path = os.path.abspath( os.path.dirname(sys.modules[__name__].__file__)) # Find out the c++ parser generator_path, generator_name = utils.find_xml_generator() # Configure the xml generator xml_generator_config = parser.xml_generator_configuration_t( xml_generator_path=generator_path, xml_generator=generator_name) # The c++ file we want to parse filename = "example.hpp" filename = this_module_dir_path + "/" + filename decls = parser.parse([filename], xml_generator_config) global_namespace = declarations.get_global_namespace(decls) ns = global_namespace.namespace("ns") # Use the free_functions method to find our function func = ns.free_function(name="myFunction") # There are two arguments: print(len(func.arguments)) # We can loop over them and print some information: for arg in func.arguments: print(arg.name, str(arg.decl_type), declarations.is_std_string(arg.decl_type), declarations.is_reference(arg.decl_type))
from pywrap.wrapper import Wrapper from pywrap import containers, namespaces, matchers, classes, functions from pygccxml import declarations wrap = Wrapper() wrap.set_number_of_files(0) module_name = wrap.module_name() mb = wrap.mb containers.extend_std_containers(mb) namespaces.include_default_copy_constructors(mb) for c in ("KProxy", ): cls = mb.class_(c) for v in cls.variables(): if declarations.is_reference(v.decl_type): v.use_make_functions = True mb.decl("get_string_vector").include() mb.namespace("test").include() cl = mb.class_("RefWrap") cl.include() functions.convert_vector_of_references_return_type(cl.mem_fun("ints")) for cl_name in ["ReturnOptional", "ReturnOptionalB", "ReturnOptionalC"]: cl = mb.class_(cl_name) cl.include() for fun in cl.member_functions(): functions.return_optional_by_value(fun)
def is_ref_or_ptr(type_): return declarations.is_pointer(type_) or declarations.is_reference(type_)
def add_self(self, output_string): # Check for exclusions if self.exclusion_critera(): return output_string # Which definition type def_adorn = "" if self.method_decl.has_static: def_adorn += "_static" # How to point to class if not self.method_decl.has_static: self_ptr = self.class_short_name + "::*" else: self_ptr = "*" # Get the arg signature arg_signature = "" num_arg_types = len(self.method_decl.argument_types) commandline_type = ( num_arg_types == 2 and self.method_decl.arguments[0].decl_type.decl_string == 'int' and self.method_decl.arguments[1].decl_type.decl_string == 'char * *') if commandline_type: arg_signature = " std::vector<std::string> " else: for idx, eachArg in enumerate(self.method_decl.argument_types): arg_signature += eachArg.decl_string if idx < num_arg_types - 1: arg_signature += ", " # Const-ness const_adorn = "" if self.method_decl.has_const: const_adorn = ' const ' # Default args default_args = "" ref_arg_defs = "" ref_args = [] args = "" origin_args = [] if commandline_type: default_args = ", py::arg(\"argc\")" else: if not self.default_arg_exclusion_criteria(): arg_types = self.method_decl.argument_types for idx, eachArg in enumerate(self.method_decl.arguments): default_args += ', py::arg("{}")'.format(eachArg.name) if declarations.is_reference(eachArg.decl_type) and ( not declarations.is_const(eachArg.decl_type.base)): ref_arg_defs += "{0} {1};\n ".format( declarations.remove_reference(eachArg.decl_type), eachArg.name) ref_args.append(eachArg.name) else: if eachArg.default_value is not None: # Hack for missing template in default args repl_value = str(eachArg.default_value) if "<DIM>" in repl_value: if "<2>" in str(arg_types[idx]).replace( " ", ""): repl_value = repl_value.replace( "<DIM>", "<2>") elif "<3>" in str(arg_types[idx]).replace( " ", ""): repl_value = repl_value.replace( "<DIM>", "<3>") default_args += ' = ' + repl_value args += ", {0} {1}".format(eachArg.decl_type, eachArg.name) origin_args.append(eachArg.name) # Call policy pointer_call_policy = self.class_info.hierarchy_attribute( 'pointer_call_policy') reference_call_policy = self.class_info.hierarchy_attribute( 'reference_call_policy') call_policy = "" is_ptr = declarations.is_pointer(self.method_decl.return_type) if pointer_call_policy is not None and is_ptr: call_policy = ", py::return_value_policy::" + pointer_call_policy is_ref = declarations.is_reference(self.method_decl.return_type) if reference_call_policy is not None and is_ref: call_policy = ", py::return_value_policy::" + reference_call_policy # method name mapping method_name = self.method_decl.name if self.method_decl.name in self.class_info.parent.function_mapping: method_name = self.class_info.parent.function_mapping[ self.method_decl.name] # return adorn return_string = self.method_decl.return_type.decl_string return_adorn = "" return_arg = "" if return_string is not "void": return_adorn = "return" return_arg = "auto ret__ =" ref_args.append("ret__") # class override name class_short_name = self.class_short_name method_dict = { 'def_adorn': def_adorn, 'method_name_alias': method_name, 'method_name': self.method_decl.name, 'return_type': self.method_decl.return_type.decl_string, 'self_ptr': self_ptr, 'arg_signature': arg_signature, 'const_adorn': const_adorn, 'class_short_name': class_short_name, 'method_docs': '" "', 'default_args': default_args, 'call_policy': call_policy, 'args': args, 'ref_arg_defs': ref_arg_defs, 'return_arg': return_arg, 'ref_args': ref_args[0] if len(ref_args) == 1 else "py::make_tuple({0})".format(', '.join(ref_args)), 'origin_args': ', '.join(origin_args), 'return_adorn': return_adorn } if commandline_type: template = self.wrapper_templates["class_method_argc_argv"] output_string += template.format(**method_dict) else: if ref_arg_defs != "": template = self.wrapper_templates["class_method_with_ref"] output_string += template.format(**method_dict) else: template = self.wrapper_templates["class_method"] output_string += template.format(**method_dict) return output_string
define_symbols=define_list, indexing_suite_version=1, # indexing_suite_version = 2, # indexing suite v2 seems to has problems with recent versions? cflags=flags_list, ) mem_funs = mb.calldefs() mem_funs.create_with_signature = True for mem_fun in mem_funs: if mem_fun.call_policies: continue # References and pointers 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) # Well, don't you want to see what is going on? #mb.print_declarations() mb.classes().always_expose_using_scope = True # Manuals exclusions try: #mb.class_("FFTConfig").member_function("StoreAudioSize").exclude() #mb.class_('FFTConfig').exclude() pass except:
def add_self(self, output_string): # Check for exclusions if self.exclusion_critera(): return output_string # Which definition type def_adorn = "" if self.method_decl.has_static: def_adorn += "_static" # How to point to class if not self.method_decl.has_static: self_ptr = self.class_short_name + "::*" else: self_ptr = "*" # Get the arg signature arg_signature = "" num_arg_types = len(self.method_decl.argument_types) for idx, eachArg in enumerate(self.method_decl.argument_types): arg_signature += eachArg.decl_string if idx < num_arg_types - 1: arg_signature += ", " # Const-ness const_adorn = "" if self.method_decl.has_const: const_adorn = ' const ' # Default args default_args = "" if not self.default_arg_exclusion_criteria(): arg_types = self.method_decl.argument_types for idx, eachArg in enumerate(self.method_decl.arguments): default_args += ', py::arg("{}")'.format(eachArg.name) if eachArg.default_value is not None: # Hack for missing template in default args repl_value = str(eachArg.default_value) if "<DIM>" in repl_value: if "<2>" in str(arg_types[idx]).replace(" ", ""): repl_value = repl_value.replace("<DIM>", "<2>") elif "<3>" in str(arg_types[idx]).replace(" ", ""): repl_value = repl_value.replace("<DIM>", "<3>") default_args += ' = ' + repl_value # Call policy pointer_call_policy = self.class_info.hierarchy_attribute( 'pointer_call_policy') reference_call_policy = self.class_info.hierarchy_attribute( 'reference_call_policy') call_policy = "" is_ptr = declarations.is_pointer(self.method_decl.return_type) if pointer_call_policy is not None and is_ptr: call_policy = ", py::return_value_policy::" + pointer_call_policy is_ref = declarations.is_reference(self.method_decl.return_type) if reference_call_policy is not None and is_ref: call_policy = ", py::return_value_policy::" + reference_call_policy method_dict = { 'def_adorn': def_adorn, 'method_name': self.method_decl.name, 'return_type': self.method_decl.return_type.decl_string, 'self_ptr': self_ptr, 'arg_signature': arg_signature, 'const_adorn': const_adorn, 'class_short_name': self.class_short_name, 'method_docs': '" "', 'default_args': default_args, 'call_policy': call_policy } template = self.wrapper_templates["class_method"] output_string += template.format(**method_dict) return output_string