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 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 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 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 add_self(self, output_string): # Check for exclusions if self.exclusion_critera(): return output_string # Which definition type # arg like char[24] base_has = hasattr(self.arg_decl.decl_type, "base") is_array = hasattr(self.arg_decl.decl_type, "size") and self.arg_decl.decl_type.size != 0 # is_vector = True if '::std::vector' in self.arg_decl.decl_type.decl_string else False char_array_type = base_has and self.arg_decl.decl_type.base.decl_string == 'char' is_static = self.arg_decl.type_qualifiers.has_static is_readonly = declarations.is_const(self.arg_decl.decl_type) arg_base_type = "" if is_array: def_adorn = "_property" if base_has: arg_base_type = self.arg_decl.decl_type.base.decl_string # elif is_vector: # def_adorn = "_property" # arg_base_type = declarations.vector_traits.element_type(self.arg_decl.decl_type).decl_string elif is_static: if is_readonly: def_adorn = "_property_readonly" else: def_adorn = "_readwrite" def_adorn += "_static" # if declarations.is_arithmetic(self.arg_decl.decl_type): arg_base_type = self.arg_decl.decl_type.decl_string else: if is_readonly: def_adorn = "_readonly" else: def_adorn = "_readwrite" simple_arg_dict = { 'def_adorn': def_adorn, 'arg_name': self.arg_decl.name, 'arg_base_type': arg_base_type, 'class_short_name': self.class_short_name } if is_array: if char_array_type: template = self.wrapper_templates["class_char_array_args"] else: template = self.wrapper_templates["class_normal_array_args"] # elif is_vector: # template = self.wrapper_templates["class_normal_array_args"] elif is_static and is_readonly: template = self.wrapper_templates["class_static_readonly_args"] else: template = self.wrapper_templates["class_simple_args"] output_string += template.format(**simple_arg_dict) return output_string
def filter_decls(mb): mb.global_ns.exclude() fx_ns = mb.namespace( 'FX' ) fx_ns.include() fx_ns.decls( declarations_to_exclude.is_excluded ).exclude() fx_ns.decls( lambda decl: decl.name.startswith('FXIPCMsgHolder') ).exclude() fx_ns.namespace( 'Pol' ).exclude() fx_ns.decls( files_to_exclude.is_excluded ).exclude() fx_ns.class_( 'QValueList<FX::Pol::knowReferrers::ReferrerEntry>').exclude() try: fx_ns.variables( 'metaClass').exclude() except: pass try: fx_ns.class_( 'QPtrVector<FX::Generic::BoundFunctorV>').exclude() except: pass #Niall? wrapper for this function could not be compiled #TnFXSQLDBStatement = fx_ns.class_( 'TnFXSQLDBStatement' ) #TnFXSQLDBStatement.member_function( name='bind', arg_types=[None,None,None] ).exclude() for func in fx_ns.calldefs(): #I want to exclude all functions that returns pointer to pointer #and returns pointer to fundamental type if declarations.is_pointer( func.return_type ): temp = declarations.remove_pointer( func.return_type ) if declarations.is_fundamental( temp ) and not declarations.is_const(temp): func.exclude() temp = declarations.remove_cv( func.return_type ) temp = declarations.remove_pointer( temp ) if declarations.is_pointer( temp ): func.exclude()
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 wrap_one_call_policy(fn): rt = fn.return_type if fn.return_type.decl_string == "char const *": return # use default for strings if fn.return_type.decl_string == "char *": return # use default for strings elif fn.return_type.decl_string == "void *": return # use default for void pointers elif fn.return_type.decl_string == "::GLvoid const *": return # use default for void pointers parent_ref = declarations.reference_t(declarations.declarated_t(fn.parent)) if declarations.is_reference(rt): # Need type without reference for next type checks nonref_rt = rt.base if declarations.is_arithmetic(nonref_rt) or declarations.is_enum( nonref_rt): # returning const& double can cause compile trouble if return_internal_reference is used if declarations.is_const(nonref_rt): fn.call_policies = return_value_policy(copy_const_reference) return # int& might need to be copy_non_const_reference... else: fn.call_policies = return_value_policy( copy_non_const_reference) return # Const string references should be copied to python strings if declarations.is_std_string(nonref_rt) and declarations.is_const( nonref_rt): fn.call_policies = return_value_policy(copy_const_reference) return # Returning reference to this same class looks like return_self() [does this always work?] if declarations.is_same(parent_ref, rt): fn.call_policies = return_self() return elif declarations.is_pointer(rt): # Clone methods if re.search(r'^clone', fn.name): fn.call_policies = return_value_policy(reference_existing_object) return else: return # Everything else probably returns an internal reference fn.call_policies = return_internal_reference() return
def wrap_one_call_policy(fn): rt = fn.return_type if fn.return_type.decl_string == "char const *": return # use default for strings if fn.return_type.decl_string == "char *": return # use default for strings elif fn.return_type.decl_string == "void *": return # use default for void pointers elif fn.return_type.decl_string == "::GLvoid const *": return # use default for void pointers parent_ref = declarations.reference_t(declarations.declarated_t(fn.parent)) if declarations.is_reference(rt): # Need type without reference for next type checks nonref_rt = rt.base if declarations.is_arithmetic(nonref_rt) or declarations.is_enum(nonref_rt): # returning const& double can cause compile trouble if return_internal_reference is used if declarations.is_const(nonref_rt): fn.call_policies = return_value_policy(copy_const_reference) return # int& might need to be copy_non_const_reference... else: fn.call_policies = return_value_policy(copy_non_const_reference) return # Const string references should be copied to python strings if declarations.is_std_string(nonref_rt) and declarations.is_const(nonref_rt): fn.call_policies = return_value_policy(copy_const_reference) return # Returning reference to this same class looks like return_self() [does this always work?] if declarations.is_same(parent_ref, rt): fn.call_policies = return_self() return elif declarations.is_pointer(rt): # Clone methods if re.search(r'^clone', fn.name): fn.call_policies = return_value_policy(reference_existing_object) return else: return # Everything else probably returns an internal reference fn.call_policies = return_internal_reference() return
def wrapper_type( self ): tmpl = "%(namespace)s::%(constness)sarray_1_t< %(item_type)s, %(array_size)d>" constness = '' if declarations.is_const( self.declaration.type ): constness = 'const_' result = tmpl % { 'namespace' : code_repository.array_1.namespace , 'constness' : constness , 'item_type' : declarations.array_item_type( self.declaration.type ).decl_string , 'array_size': declarations.array_size( self.declaration.type ) } return declarations.dummy_type_t( result )
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 _get_wrapper_type( self ): ns_name = code_repository.array_1.namespace if declarations.is_const( self.declaration.type ): class_name = 'const_array_1_t' else: class_name = 'array_1_t' decl_string = declarations.templates.join( '::'.join( [ns_name, class_name] ) , [ declarations.array_item_type( self.declaration.type ).decl_string , str( declarations.array_size( self.declaration.type ) ) ]) return declarations.dummy_type_t( decl_string )
def test(self): """ Test the find_noncopyable_vars function """ # The ptr1 variable in the holder struct can be copied, # but not the ptr2 variable holder = self.global_ns.class_("holder") nc_vars = declarations.find_noncopyable_vars(holder) self.assertEqual(len(nc_vars), 1) self.assertEqual(nc_vars[0].name, "ptr2") self.assertTrue(declarations.is_pointer(nc_vars[0].decl_type)) self.assertTrue(declarations.is_const(nc_vars[0].decl_type))
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 test5(self): code = 'char const arr[4] = {};' src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) arr_type = global_ns.variable('arr').decl_type if self.config.xml_generator == "gccxml": self.assertTrue('char [4] const' == arr_type.decl_string, arr_type.decl_string) else: self.assertTrue('char const [4]' == arr_type.decl_string, arr_type.decl_string) self.assertTrue(declarations.is_array(arr_type)) self.assertTrue(declarations.is_const(arr_type))
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 _get_call_policies(self): if self.__call_policies: return self.__call_policies if self.container_traits not in declarations.sequential_container_traits: # TODO: find out why map's don't like the policy return self.__call_policies element_type = None try: element_type = self.element_type except: return if declarations.is_const(element_type): element_type = declarations.remove_const(element_type) if declarations.is_pointer(element_type): self.__call_policies = call_policies.return_internal_reference() return self.__call_policies
def _get_call_policies( self ): if self.__call_policies: return self.__call_policies if self.container_traits not in declarations.sequential_container_traits: #TODO: find out why map's don't like the policy return self.__call_policies element_type = None try: element_type = self.element_type except: return if declarations.is_const( element_type ): element_type = declarations.remove_const( element_type ) if declarations.is_pointer( element_type ): self.__call_policies = call_policies.return_internal_reference() return self.__call_policies
def wrapper_type( self ): tmpl = "%(namespace)s::%(constness)sarray_1_t< %(item_type)s, %(array_size)d>" item_type = declarations.array_item_type(self.declaration.decl_type) is_noncopyable = not declarations.is_fundamental(item_type) and \ declarations.is_noncopyable(item_type) constness = '' if declarations.is_const(self.declaration.decl_type) or is_noncopyable: constness = 'const_' result = tmpl % { 'namespace' : code_repository.array_1.namespace , 'constness' : constness , 'item_type' : declarations.array_item_type( self.declaration.decl_type ).decl_string , 'array_size': declarations.array_size( self.declaration.decl_type ) } return declarations.dummy_type_t( result )
def _create_impl(self): templates = declarations.templates call_invocation = declarations.call_invocation ns_name = code_repository.array_1.namespace if declarations.is_const( self.array_type ): fn_name = 'register_const_array_1' else: fn_name = 'register_array_1' fn_def_tmpl_args = [ declarations.array_item_type(self.array_type).decl_string , str( declarations.array_size(self.array_type) ) ] if not self.call_policies.is_default(): fn_def_tmpl_args.append( self.call_policies.create(self, call_policies.CREATION_POLICY.AS_TEMPLATE_ARGUMENT ) ) fn_def = templates.join( '::'.join( [ns_name, fn_name] ), fn_def_tmpl_args ) return call_invocation.join( fn_def, [ '"%s"' % self._create_name() ] ) + ';'
def test5(self): code = 'char const arr[4] = {};' src_reader = parser.source_reader_t(self.config) global_ns = declarations.get_global_namespace( src_reader.read_string(code)) arr_type = global_ns.variable('arr').decl_type if self.config.xml_generator == "gccxml": self.assertTrue( 'char [4] const' == arr_type.decl_string, arr_type.decl_string) else: self.assertTrue( 'char const [4]' == arr_type.decl_string, arr_type.decl_string) self.assertTrue( declarations.is_array(arr_type)) self.assertTrue( declarations.is_const(arr_type))
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 __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 _get_has_setter( self ): if declarations.is_const( declarations.remove_reference( self.declaration.type ) ): return False elif python_traits.is_immutable( self._get_exported_var_type() ): return True else: pass no_ref = declarations.remove_reference( self.declaration.type ) no_const = declarations.remove_const( no_ref ) base_type = declarations.remove_alias( no_const ) if not isinstance( base_type, declarations.declarated_t ): return True #TODO ???? decl = base_type.declaration if decl.is_abstract: return False if declarations.has_destructor( decl ) and not declarations.has_public_destructor( decl ): return False if not declarations.has_copy_constructor(decl): return False return True
def __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 _get_has_setter(self): return not declarations.is_const(self.declaration.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
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 parse_class(class_, stream, top_level=True): """ Write bindings for a class """ full_class_name_ = full_class_name(class_) base_classes = class_.recursive_bases init_function_name = "pybind11_init_" + mangled_name(class_) if top_level: stream("inline %s %s(py::module &m)" % (bind_class_name(class_), init_function_name)) stream("{") stream(" %s instance(m, \"%s\");" % (bind_class_name(class_), class_.name.replace('<', '_').replace( '>', '_').replace('::', '_'))) stream(" instance") else: stream(" %s(instance, \"%s\")" % (bind_class_name(class_), class_.name.replace('<', '_').replace( '>', '_').replace('::', '_'))) if not class_.is_abstract: for constructor in class_.constructors(): if constructor.parent.name != class_.name: continue if constructor.access_type != 'public': continue stream(" .def(py::init<%s>())" % ', '.join( [arg.decl_type.decl_string for arg in constructor.arguments])) for operator in class_.operators(allow_empty=True): if operator.parent.name != class_.name: continue if operator.access_type != 'public': continue const = ' const' if operator.has_const else '' if operator.symbol == '[]': stream( " .def(\"__setitem__\", (%s (%s::*)(%s)) &%s::operator%s)" % (operator.return_type, full_class_name_, ', '.join([ arg.decl_type.decl_string for arg in operator.arguments ]), full_class_name_, operator.symbol)) stream( " .def(\"__getitem__\", (%s (%s::*)(%s)%s) &%s::operator%s)" % (operator.return_type, full_class_name_, ', '.join([ arg.decl_type.decl_string for arg in operator.arguments ]), const, full_class_name_, operator.symbol)) elif operator.symbol in operator_map: stream(" .def(\"%s\", (%s (%s::*)(%s)%s) &%s::operator%s)" % (operator_map[operator.symbol], operator.return_type, full_class_name_, ', '.join([ arg.decl_type.decl_string for arg in operator.arguments ]), const, full_class_name_, operator.symbol)) else: print("WARNING: no built-in type for operator", operator.name) all_methods = set() overloaded_methods = set() for member in class_.public_members: if member.parent.name != class_.name: continue if member.__class__.__name__ != "member_function_t": continue if member.name in all_methods: overloaded_methods.add(member.name) else: all_methods.add(member.name) # this code block separates method pairs that look like "XXX()" and # "setXXXX()" and flags them to be used as set-s and get-s to define a # property. use_properties = False property_set_methods = set() property_get_methods = set() if use_properties: def uncapitalize(s): return s[:1].lower() + s[1:] if s else '' property_set_methods = set([ m for m in class_.public_members if m.name[:3] == "set" and m.name not in overloaded_methods and uncapitalize(m.name[3:]) not in overloaded_methods and uncapitalize(m.name[3:]) in all_methods ]) property_get_methods = set([ m for m in class_.public_members if 'set%s' % m.name.capitalize() not in overloaded_methods and m.name not in overloaded_methods and 'set%s' % m.name.capitalize() in all_methods ]) unique_properties = set() for prop in property_set_methods: static = '_static' if prop.has_static else '' set_name = prop.name get_name = uncapitalize(prop.name[3:]) if get_name not in unique_properties: stream(" .def_property%s(\"%s\", &%s::%s, &%s::%s)" % (static, get_name, full_class_name_, get_name, full_class_name_, set_name)) unique_properties.add(get_name) for member in class_.public_members: if member.parent.name != class_.name: continue if member.__class__.__name__ != "member_function_t": continue static = '_static' if member.has_static else '' const = ' const' if member.has_const else '' args_ = (', ' + ', '.join(["py::arg(\"%s\") = %s" % (arg.name, arg.default_value) if arg.default_value is not None else "py::arg(\"%s\")" % (arg.name) for arg in member.arguments])) \ if len(member.arguments) != 0 else '' if member in property_set_methods or member in property_get_methods: continue if member.name in overloaded_methods: stream(" .def%s(\"%s\", (%s (%s*)(%s)%s) &%s::%s%s)" % (static, member.name, member.return_type, ("" if member.has_static else full_class_name_ + "::"), ', '.join([ arg.decl_type.decl_string for arg in member.arguments ]), const, full_class_name_, member.name, args_)) else: stream(" .def%s(\"%s\", &%s::%s%s)" % (static, member.name, full_class_name_, member.name, args_)) for variable in class_.variables(allow_empty=True): if variable.parent.name != class_.name: continue if variable.access_type == "public": static = '_static' if variable.type_qualifiers.has_static else '' if declarations.is_const(variable): stream( " .def_readonly%s(\"%s\", &%s::%s)" % (static, variable.name, full_class_name_, variable.name)) else: stream( " .def_readwrite%s(\"%s\", &%s::%s)" % (static, variable.name, full_class_name_, variable.name)) stream(" ;") for enum in class_.enumerations(allow_empty=True): stream(" py::enum_<%s::%s>(%s, \"%s\")" % (full_class_name_, enum.name, "instance", enum.name)) for (name, num) in enum.values: stream(" .value(\"%s\", %s::%s::%s)" % (name, full_class_name_, enum.name, name)) stream(" .export_values();") for decl in class_.declarations: if type(decl).__name__.find('class_t') != -1: parse_class(decl, stream, False) parsed_classes.add(class_) if top_level: stream(" return instance;") stream("}") return init_function_name else: return
def has_setter(self): return declarations.is_pointer( self.declaration.type ) \ and not declarations.is_const( self.declaration.type )
def wrapped_class_type(self): wrapped_cls_type = declarations.declarated_t(self.declaration.parent) if declarations.is_const(self.declaration.type): wrapped_cls_type = declarations.const_t(wrapped_cls_type) return declarations.reference_t(wrapped_cls_type)
print("My type is: " + str(a.decl_type)) # > My type is: int const # If we print real python type: print("My type is : " + str(type(a.decl_type))) # > My type is: <class 'pygccxml.declarations.cpptypes.const_t'> # Types are nested in pygccxml. This means that you will get information # about the first type only. You can access the "base" type by removing # the const part: print("My base type is: " + str(type(declarations.remove_const(a.decl_type)))) # > My base type is: <class 'pygccxml.declarations.cpptypes.int_t'> # You use the is_const function to check for a type: print("Is 'a' a const ?: " + str(declarations.is_const(a.decl_type))) # > Is 'a' a const ?: True # A more complex example with variable b: b = ns.variables()[1] print("My type is: " + str(type(b.decl_type))) # > My type is: <class 'pygccxml.declarations.cpptypes.pointer_t'> print("My type is: " + str(type( declarations.remove_const( declarations.remove_volatile( declarations.remove_pointer(b.decl_type)))))) # > My type is: <class 'pygccxml.declarations.cpptypes.int_t'> # The declarations module contains much more methods allowing you to # navigate the nested types list.
print("My type is: " + str(a.decl_type)) # > My type is: int const # If we print real python type: print("My type is : " + str(type(a.decl_type))) # > My type is: <class 'pygccxml.declarations.cpptypes.const_t'> # Types are nested in pygccxml. This means that you will get information # about the first type only. You can access the "base" type by removing # the const part: print("My base type is: " + str(type(declarations.remove_const(a.decl_type)))) # > My base type is: <class 'pygccxml.declarations.cpptypes.int_t'> # You use the is_const function to check for a type: print("Is 'a' a const ?: " + str(declarations.is_const(a.decl_type))) # > Is 'a' a const ?: True # A more complex example with variable b: b = ns.variables()[1] print("My type is: " + str(type(b.decl_type))) # > My type is: <class 'pygccxml.declarations.cpptypes.pointer_t'> print("My type is: " + str( type( declarations.remove_const( declarations.remove_volatile( declarations.remove_pointer(b.decl_type)))))) # > My type is: <class 'pygccxml.declarations.cpptypes.int_t'> # The declarations module contains much more methods allowing you to # navigate the nested types list.
def has_setter( self ) : return declarations.is_pointer( self.declaration.type ) \ and not declarations.is_const( self.declaration.type )
def wrapped_class_type( self ): wrapped_cls_type = declarations.declarated_t( self.declaration.parent ) if declarations.is_const( self.declaration.type ): wrapped_cls_type = declarations.const_t( wrapped_cls_type ) return declarations.reference_t( wrapped_cls_type )
def _get_has_setter( self ): return not declarations.is_const( self.declaration.type )