[pygccxml-commit] SF.net SVN: pygccxml: [495] pyplusplus_dev/unittests
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-08-30 10:05:07
|
Revision: 495 Author: roman_yakovenko Date: 2006-08-30 03:04:41 -0700 (Wed, 30 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=495&view=rev Log Message: ----------- adding support for BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS and BOOST_PYTHON_FUNCTION_OVERLOADS macros Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/test_all.py Added Paths: ----------- pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp pyplusplus_dev/unittests/overloads_macro_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-08-30 10:04:41 UTC (rev 495) @@ -64,9 +64,13 @@ from calldef import constructor_t from calldef import static_method_t from calldef import casting_operator_t +from calldef import mem_fun_overloads_t +from calldef import free_fun_overloads_t from calldef import casting_constructor_t from calldef import constructor_wrapper_t +from calldef import mem_fun_overloads_class_t from calldef import casting_member_operator_t +from calldef import free_fun_overloads_class_t from calldef import copy_constructor_wrapper_t from calldef import null_constructor_wrapper_t @@ -85,7 +89,7 @@ from member_variable import mem_var_ref_t from member_variable import mem_var_ref_wrapper_t -from class_declaration import class_t +from class_declaration import class_t from class_declaration import class_wrapper_t from class_declaration import class_declaration_t Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-08-30 10:04:41 UTC (rev 495) @@ -5,6 +5,7 @@ import os import algorithm +import code_creator import declaration_based import class_declaration from pygccxml import declarations @@ -84,7 +85,7 @@ raise NotImplementedError() def _get_function_type_alias( self ): - return 'function_ptr_t' + return self.alias + '_function_type' function_type_alias = property( _get_function_type_alias ) def _get_exported_class_alias( self ): @@ -1126,3 +1127,218 @@ + '();' + +class calldef_overloads_class_t( code_creator.code_creator_t ): + def __init__( self, functions ): + #precondition: all member functions belong to same class and + #they all have same alias, otherwise it does not makes sense + code_creator.code_creator_t.__init__( self ) + self._functions = functions + self._functions.sort() #I need this for "stabble" code generation + self._max_fun = None #function with maximal number of arguments + + @property + def functions( self ): + return self._functions + + def min_max_num_of_args( self ): + #returns tuple( minimal, maximal ) number of arguments + min_ = None + max_ = 0 + for f in self.functions: + args_ = len( f.arguments ) + if None is min_: + min_ = args_ + else: + min_ = min( min_, args_ ) + max_tmp = max( max_, args_ ) + if max_ < max_tmp: + max_ = max_tmp + self._max_fun = f + return ( min_, max_ ) + + @property + def max_function( self ): + if not self._max_fun: + initialize_max_fun_var = self.min_max_num_of_args() + return self._max_fun + + @property + def max_function_identifier( self ): + return algorithm.create_identifier( self, declarations.full_name( self.max_function ) ) + + @property + def alias( self ): + return self.functions[0].alias + + @property + def parent_decl( self ): + return self.functions[0].parent + + @property + def name( self ): + return '%s_%s_overloads' % ( self.parent_decl.alias, self.alias ) + +class mem_fun_overloads_class_t( calldef_overloads_class_t ): + def __init__( self, mem_funs ): + #precondition: all member functions belong to same class and + #they all have same alias, otherwise it does not makes sense + calldef_overloads_class_t.__init__( self, mem_funs ) + + def _create_impl(self): + min_, max_ = self.min_max_num_of_args() + return "BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( %(overloads_cls)s, %(fun)s, %(min)d, %(max)d )" \ + % { 'overloads_cls' : self.name + , 'fun' : self.max_function_identifier + , 'min' : min_ + , 'max' : max_ + } + +class free_fun_overloads_class_t( calldef_overloads_class_t ): + def __init__( self, free_funs ): + #precondition: all member functions belong to same class and + #they all have same alias, otherwise it does not makes sense + calldef_overloads_class_t.__init__( self, free_funs ) + + def _create_impl(self): + min_, max_ = self.min_max_num_of_args() + return "BOOST_PYTHON_FUNCTION_OVERLOADS( %(overloads_cls)s, %(fun)s, %(min)d, %(max)d )" \ + % { 'overloads_cls' : self.name + , 'fun' : self.max_function_identifier + , 'min' : min_ + , 'max' : max_ + } + +class calldef_overloads_t( code_creator.code_creator_t ): + def __init__( self, overloads_class ): + code_creator.code_creator_t.__init__( self ) + self._overloads_class = overloads_class + + @property + def overloads_class( self ): + return self._overloads_class + + def create_def_code( self ): + raise NotImplementedError() + + def create_end_def_code( self ): + raise NotImplementedError() + + def keywords_args(self): + result = [ algorithm.create_identifier( self, '::boost::python::args' ) ] + result.append( '( ' ) + args = [] + for arg in self.overloads_class.max_function.arguments: + if 0 < len( args ): + args.append( self.PARAM_SEPARATOR ) + args.append( '"%s"' % arg.name ) + result.extend( args ) + result.append( ' )' ) + return ''.join( result ) + + def _get_function_type_alias( self ): + return self.overloads_class.alias + '_function_type' + function_type_alias = property( _get_function_type_alias ) + + def create_function_type_alias_code( self, exported_class_alias=None ): + raise NotImplementedError() + + def create_overloads_cls( self ): + result = [ self.overloads_class.name ] + result.append( '( ' ) + result.append( os.linesep + self.indent( self.keywords_args(), 3 ) ) + if self.overloads_class.max_function.documentation: + result.append( os.linesep + self.indent( self.PARAM_SEPARATOR, 3 ) ) + result.append( self.overloads_class.max_function.documentation ) + result.append( ' )' ) + if self.overloads_class.max_function.call_policies: + result.append( os.linesep + self.indent('', 3) ) + result.append('[ %s ]' % self.overloads_class.max_function.call_policies.create( self ) ) + return ''.join( result ) + + def _create_impl(self): + result = [] + if not self.works_on_instance: + exported_class_alias = None + if declarations.templates.is_instantiation( self.overloads_class.max_function.parent.name ): + exported_class_alias = self.exported_class_alias + result.append( 'typedef %s %s;' % ( self.parent.decl_identifier, exported_class_alias ) ) + result.append( os.linesep ) + result.append( self.create_function_type_alias_code(exported_class_alias) ) + result.append( os.linesep * 2 ) + + result.append( self.create_def_code() + '( ' ) + result.append( os.linesep + self.indent( '"%s"' % self.overloads_class.alias ) ) + + result.append( os.linesep + self.indent( self.PARAM_SEPARATOR ) ) + result.append( self.create_function_ref_code( not self.works_on_instance ) ) + + result.append( os.linesep + self.indent( self.PARAM_SEPARATOR ) ) + result.append( self.create_overloads_cls() ) + + result.append( ' )' ) + result.append( self.create_end_def_code() ) + + if not self.works_on_instance: + #indenting and adding scope + code = ''.join( result ) + result = [ '{ //%s' % declarations.full_name( self.overloads_class.max_function ) ] + result.append( os.linesep * 2 ) + result.append( self.indent( code ) ) + result.append( os.linesep * 2 ) + result.append( '}' ) + + return ''.join( result ) + +class mem_fun_overloads_t( calldef_overloads_t ): + def __init__( self, overloads_class ): + calldef_overloads_t.__init__( self, overloads_class ) + + def create_def_code( self ): + if not self.works_on_instance: + return '%s.def' % self.parent.class_var_name + else: + return 'def' + + def create_end_def_code( self ): + if not self.works_on_instance: + return ';' + else: + return '' + + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.overloads_class.max_function.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) + + def create_function_ref_code(self, use_function_alias=False): + fname = declarations.full_name( self.overloads_class.max_function ) + if use_function_alias: + return '%s( &%s )' % ( self.function_type_alias, fname ) + elif self.overloads_class.max_function.create_with_signature: + return '(%s)( &%s )' % ( self.overloads_class.max_function.function_type().decl_string, fname ) + else: + return '&%s' % fname + + +class free_fun_overloads_t( calldef_overloads_t ): + def __init__( self, overloads_class ): + calldef_overloads_t.__init__( self, overloads_class ) + + def create_def_code( self ): + return algorithm.create_identifier( self, '::boost::python::def' ) + + def create_end_def_code( self ): + return ';' + + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.overloads_class.max_function.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) + + def create_function_ref_code(self, use_function_alias=False): + fname = declarations.full_name( self.overloads_class.max_function ) + if use_function_alias: + return '%s( &%s )' % ( self.function_type_alias, fname ) + elif self.overloads_class.max_function.create_with_signature: + return '(%s)( &%s )' % ( self.overloads_class.max_function.function_type().decl_string, fname ) + else: + return '&%s' % fname Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-08-30 10:04:41 UTC (rev 495) @@ -7,7 +7,7 @@ import types import scoped import calldef -import algorithm +import algorithm import smart_pointers import declaration_based from pygccxml import declarations @@ -36,26 +36,26 @@ def _get_class_var_name(self): return self.alias + '_exposer' class_var_name = property( _get_class_var_name ) - + def is_exposed_using_scope(self): if self.declaration.always_expose_using_scope: return True - return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) + return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) @property def typedef_name( self ): return self.class_var_name + '_t' - + def _generate_code_with_scope(self): result = [] scope_var_name = self.alias + '_scope' result.append( 'typedef ' + self._generate_class_definition() + ' ' + self.typedef_name + ';') result.append( self.typedef_name + ' ' + self.class_var_name ) result[-1] = result[-1] + ' = '+ self.typedef_name + '("%s");' % self.declaration.alias - + result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) result[-1] = result[-1] + ' ' + scope_var_name - result[-1] = result[-1] + '( %s );' % self.class_var_name + result[-1] = result[-1] + '( %s );' % self.class_var_name for x in self.creators: if not x.works_on_instance: @@ -64,13 +64,13 @@ result.append( '%s.%s;' % ( self.class_var_name, x.create() ) ) code = os.linesep.join( result ) - + result = [ '{ //scope begin' ] result.append( self.indent( code ) ) result.append( '} //scope end' ) - + return os.linesep.join( result ) - + def _create_impl(self): if self.is_exposed_using_scope(): return self._generate_code_with_scope() @@ -87,7 +87,7 @@ self._wrapper = wrapper self.works_on_instance = False self._user_declarations = [] - + def _get_wrapper( self ): return self._wrapper def _set_wrapper( self, new_wrapper ): @@ -109,17 +109,17 @@ assert held_type # should be non emptry string self.declaration.held_type = held_type held_type = property( _get_held_type, _set_held_type ) - + def _exported_base_classes(self): if not self.declaration.bases: - return {}, {} + return {}, {} base_classes = {} for hierarchy_info in self.declaration.recursive_bases: if hierarchy_info.access_type == declarations.ACCESS_TYPES.PRIVATE: - continue + continue base_classes[ id( hierarchy_info.related_class ) ] = hierarchy_info base_classes_size = len( base_classes ) - creators = {} + creators = {} for creator in algorithm.make_flatten_generator( self.top_parent.body.creators ): if not isinstance( creator, class_t ): continue @@ -128,7 +128,7 @@ if len( creators ) == base_classes_size: break #all classes has been found return base_classes, creators - + def _get_base_operators(self, base_classes, base_creators): #May be in future I will redefine operators on wrapper class #thus I will support [protected|private] [ [not|pure|] virtual] operators. @@ -137,20 +137,20 @@ hierarchy_info = base_classes[ id( base_creator.declaration )] if hierarchy_info.access_type != declarations.ACCESS_TYPES.PUBLIC: continue - base_operator_creators = filter( lambda creator: + base_operator_creators = filter( lambda creator: isinstance( creator, calldef.operator_t ) and isinstance( creator.declaration, declarations.member_operator_t ) - and creator.declaration.access_type + and creator.declaration.access_type == declarations.ACCESS_TYPES.PUBLIC , base_creator.creators ) operator_creators.extend( base_operator_creators ) return operator_creators - + def _generate_noncopyable(self): if self.declaration.noncopyable: return algorithm.create_identifier( self, '::boost::noncopyable' ) - def _generate_bases(self, base_creators): + def _generate_bases(self, base_creators): bases = [] assert isinstance( self.declaration, declarations.class_t ) for base_desc in self.declaration.bases: @@ -171,11 +171,11 @@ return self.held_type else: return None - + def _generate_class_definition(self, base_creators): class_identifier = algorithm.create_identifier( self, '::boost::python::class_' ) args = [] - + held_type = self._generated_held_type() if self.wrapper: if held_type and not self.target_configuration.boost_python_has_wrapper_held_type: @@ -185,8 +185,8 @@ args.append( algorithm.create_identifier( self, self.declaration.decl_string ) ) bases = self._generate_bases(base_creators) if bases: - args.append( bases ) - + args.append( bases ) + if held_type: args.append( held_type ) notcopyable = self._generate_noncopyable() @@ -205,7 +205,7 @@ if ( self.declaration.is_abstract \ or not declarations.has_any_non_copyconstructor(self.declaration) ) \ and not self.wrapper \ - or ( declarations.has_destructor( self.declaration ) + or ( declarations.has_destructor( self.declaration ) and not declarations.has_public_destructor( self.declaration ) ): #TODO: or self.declaration has public constructor and destructor result.append( ", " ) @@ -253,12 +253,12 @@ @property def typedef_name( self ): return self.class_var_name + '_t' - + def create_typedef_code( self ): base_classes, base_creators = self._exported_base_classes() return 'typedef ' + self._generate_class_definition(base_creators) + ' ' + self.typedef_name + ';' - - + + def _generate_code_with_scope(self): result = [] scope_var_name = self.alias + '_scope' @@ -269,19 +269,19 @@ class_constructor, used_init = self._generate_constructor() result[-1] = result[-1] + self.typedef_name + class_constructor result[-1] = result[-1] + ';' - + result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) result[-1] = result[-1] + ' ' + scope_var_name - result[-1] = result[-1] + '( %s );' % self.class_var_name + result[-1] = result[-1] + '( %s );' % self.class_var_name creators = self.creators if self.declaration.redefine_operators: creators = self.creators + self._get_base_operators(base_classes, base_creators) - + for x in creators: if x is used_init: continue - if isinstance( x, calldef.calldef_t ): + if isinstance( x, ( calldef.calldef_t, calldef.calldef_overloads_t ) ): x.works_on_instance = False code = x.create() if code: @@ -295,18 +295,18 @@ result.append( '%s.%s;' % ( self.class_var_name, x.create() ) ) code = os.linesep.join( result ) - + result = [ '{ //%s' % declarations.full_name( self.declaration ) ] result.append( self.indent( code ) ) result.append( '}' ) - + return os.linesep.join( result ) def is_exposed_using_scope(self): if self.declaration.always_expose_using_scope: return True - return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) - + return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) + def _create_impl(self): if self.is_exposed_using_scope(): return self._generate_code_with_scope() @@ -323,13 +323,13 @@ scoped.scoped_t.__init__( self, declaration=declaration ) self._class_creator = class_creator self._base_wrappers = [] - + def _get_wrapper_alias( self ): return self.declaration.wrapper_alias def _set_wrapper_alias( self, walias ): self.declaration.wrapper_alias = walias wrapper_alias = property( _get_wrapper_alias, _set_wrapper_alias ) - + def _get_base_wrappers( self ): if self.declaration.is_abstract and not self._base_wrappers: bases = [ hi.related_class for hi in self.declaration.bases ] @@ -366,15 +366,15 @@ def _get_held_type(self): return self._class_creator.held_type held_type = property( _get_held_type ) - + def _get_boost_wrapper_identifier(self): boost_wrapper = algorithm.create_identifier( self, '::boost::python::wrapper' ) - return declarations.templates.join( boost_wrapper, [self.exposed_identifier] ) + return declarations.templates.join( boost_wrapper, [self.exposed_identifier] ) boost_wrapper_identifier = property( _get_boost_wrapper_identifier ) - + def _create_bases(self): return ', '.join( [self.exposed_identifier, self.boost_wrapper_identifier] ) - + def _create_impl(self): answer = ['struct %s : %s {' % ( self.wrapper_alias, self._create_bases() )] answer.append( '' ) @@ -382,12 +382,11 @@ answer.append( '' ) answer.append( '};' ) return os.linesep.join( answer ) - - - - - - - - - \ No newline at end of file + + + + + + + + Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-08-30 10:04:41 UTC (rev 495) @@ -11,10 +11,10 @@ class calldef_t(decl_wrapper.decl_wrapper_t): """base class for all decl_wrappers callable objects classes.""" - + BOOST_PYTHON_MAX_ARITY = 10 """Boost.Python configuration macro value. - + A function has more than BOOST_PYTHON_MAX_ARITY arguments, will not compile. You should adjust BOOST_PYTHON_MAX_ARITY macro. For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html @@ -64,7 +64,7 @@ def has_wrapper( self ): """returns True, if function - wrapper is needed - + The functionality by this function is uncomplete. So please don't use it in your code. """ @@ -176,7 +176,17 @@ def __init__(self, *arguments, **keywords): declarations.member_function_t.__init__( self, *arguments, **keywords ) calldef_t.__init__( self ) + self._use_overload_macro = False + def get_use_overload_macro(self): + return self._use_overload_macro + def set_use_overload_macro(self, use_macro): + self._use_overload_macro = use_macro + use_overload_macro = property( get_use_overload_macro, set_use_overload_macro + , doc="boolean, if True, will use BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS macro to expose declarations" \ + +"Default value is False.") + + class constructor_t( declarations.constructor_t, calldef_t ): """defines a set of properties, that will instruct Py++ how to expose the constructor""" def __init__(self, *arguments, **keywords): @@ -330,7 +340,17 @@ def __init__(self, *arguments, **keywords): declarations.free_function_t.__init__( self, *arguments, **keywords ) calldef_t.__init__( self ) + self._use_overload_macro = False + def get_use_overload_macro(self): + return self._use_overload_macro + def set_use_overload_macro(self, use_macro): + self._use_overload_macro = use_macro + use_overload_macro = property( get_use_overload_macro, set_use_overload_macro + , doc="boolean, if True, will use BOOST_PYTHON_FUNCTION_OVERLOADS macro to expose declarations" \ + +"Default value is False.") + + class free_operator_t( declarations.free_operator_t, calldef_t ): """defines a set of properties, that will instruct Py++ how to expose the free operator""" def __init__(self, *arguments, **keywords): Modified: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-08-30 10:04:41 UTC (rev 495) @@ -21,15 +21,15 @@ This class will split code, generated for huge classes, to few files. Next strategy will be used: 1. New directory with class alias name will be created. - 2. pyplusplus will generate + 2. pyplusplus will generate wrapper header - header that will contain code generated for class wrappers classes h/cpp - will contain registration code for internal classes memfun h/cpp - will contain registration code for member functions alias + _main h/cpp this class will contain main registration function. - """ + """ - def __init__(self, extmodule, directory_path, huge_classes, num_of_functions_per_file=25): + def __init__(self, extmodule, directory_path, huge_classes, num_of_functions_per_file=20): multiple_files.multiple_files_t.__init__(self, extmodule, directory_path) self.huge_classes = huge_classes self.num_of_functions_per_file = num_of_functions_per_file @@ -44,7 +44,7 @@ #not supported yet #, self.split_internal_member_variables ] - + def create_base_fname( self, class_creator, pattern ): return "_%s__%s" % ( class_creator.alias, pattern ) @@ -55,7 +55,7 @@ answer = [] if self.extmodule.license: answer.append( self.extmodule.license.create() ) - + answer.append( self.create_include_code( [class_creator] ) ) answer.append( '' ) answer.append( self.create_namespaces_code( [class_creator] ) ) @@ -63,27 +63,27 @@ if class_creator.wrapper: answer.append( class_creator.wrapper.create() ) class_creator.wrapper.create = lambda: '' - + answer.append( '' ) answer.append( class_creator.create_typedef_code() ) - + code = os.linesep.join( answer ) wrapper_code = self.create_header( self.create_base_fname(class_creator, 'wrapper'), code ) header_file = os.path.join( self.directory_path, self.wrapper_header(class_creator) ) self.write_file( header_file, wrapper_code ) - + def split_internal_creators( self, class_creator, creators, pattern ): file_path = os.path.join( self.directory_path , self.create_base_fname( class_creator, pattern ) ) - + function_name = 'register_%(cls_alias)s_%(pattern)s' \ % { 'cls_alias' : class_creator.alias, 'pattern' : pattern } - + function_decl = 'void %(fname)s( %(exposer_type)s& %(var_name)s )' \ % { 'fname' : function_name , 'exposer_type' : class_creator.typedef_name , 'var_name' : class_creator.class_var_name } - + #writting header file header_code = [ '#include "%s"' % self.wrapper_header( class_creator ) ] header_code.append( '' ) @@ -91,12 +91,12 @@ self.write_file( file_path + self.HEADER_EXT , self.create_header( class_creator.alias + '_' + pattern , os.linesep.join(header_code) ) ) - - #writting source file + + #writting source file source_code = [] if self.extmodule.license: source_code.append( self.extmodule.license.create() ) - + #relevant header file head_headers = [ self.create_base_fname( class_creator, pattern + self.HEADER_EXT ) ] source_code.append( self.create_include_code( creators, head_headers ) ) @@ -132,7 +132,7 @@ self.split_internal_creators( class_creator, creators, 'unnamed_enums' ) return 'unnamed_enums' - def split_internal_calldefs( self, class_creator, calldef_types, pattern ): + def split_internal_calldefs( self, class_creator, calldef_types, pattern ): creators = filter( lambda x: isinstance(x, calldef_types ), class_creator.creators ) grouped_creators = pypp_utils.split_sequence( creators, self.num_of_functions_per_file ) if len( grouped_creators ) == 1: @@ -140,8 +140,8 @@ creator.works_on_instance = False self.split_internal_creators( class_creator, creators, pattern ) return pattern - else: - patterns = [] + else: + patterns = [] for index, group in enumerate( grouped_creators ): pattern_tmp = pattern + str( index ) patterns.append( pattern_tmp ) @@ -151,24 +151,24 @@ return patterns def split_internal_memfuns( self, class_creator ): - calldef_types = ( code_creators.mem_fun_t ) + calldef_types = ( code_creators.mem_fun_t ) return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns' ) def split_internal_v_memfuns( self, class_creator ): - calldef_types = ( code_creators.mem_fun_v_t ) + calldef_types = ( code_creators.mem_fun_v_t ) return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns_virtual' ) def split_internal_pv_memfuns( self, class_creator ): - calldef_types = ( code_creators.mem_fun_pv_t ) + calldef_types = ( code_creators.mem_fun_pv_t ) return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns_pvirtual' ) def split_internal_protected_memfuns( self, class_creator ): - calldef_types = ( + calldef_types = ( code_creators.mem_fun_protected_t , code_creators.mem_fun_protected_s_t , code_creators.mem_fun_protected_v_t , code_creators.mem_fun_protected_pv_t ) - + return self.split_internal_calldefs( class_creator, calldef_types, 'protected_memfuns' ) @@ -183,13 +183,13 @@ , class_creator.creators ) self.split_internal_creators( class_creator, creators, 'memvars' ) return 'memvars' - + def split_class_impl( self, class_creator): if not class_creator.declaration in self.huge_classes: return super( class_multiple_files_t, self ).split_class_impl( class_creator ) - + class_creator.declaration.always_expose_using_scope = True - + function_name = 'register_%s_class' % class_creator.alias file_path = os.path.join( self.directory_path, class_creator.alias ) # Write the .h file... @@ -197,9 +197,9 @@ self.write_file( header_name , self.create_header( class_creator.alias , self.create_function_code( function_name ) ) ) - + self.write_wrapper( class_creator ) - + tail_headers = [] for splitter in self.internal_splitters: pattern = splitter( class_creator ) @@ -211,16 +211,16 @@ assert( isinstance( pattern, list ) ) for p in pattern: tail_headers.append( self.create_base_fname( class_creator, p + self.HEADER_EXT ) ) - #writting source file + #writting source file source_code = [] if self.extmodule.license: source_code.append( self.extmodule.license.create() ) - + source_code.append( self.create_include_code( [class_creator], tail_headers=tail_headers ) ) source_code.append( '' ) source_code.append( self.create_namespaces_code( [class_creator] ) ) - + for creator in class_creator.user_declarations: source_code.append( '' ) source_code.append( creator.create() ) @@ -234,10 +234,10 @@ source_code.append( '' ) source_code.append( '}' ) self.write_file( file_path + self.SOURCE_EXT, os.linesep.join( source_code ) ) - + # Replace the create() method so that only the register() method is called # (this is called later for the main source file). class_creator.create = lambda: function_name +'();' self.include_creators.append( code_creators.include_t( header_name ) ) self.split_header_names.append(header_name) - self.split_method_names.append(function_name) \ No newline at end of file + self.split_method_names.append(function_name) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 10:04:41 UTC (rev 495) @@ -127,6 +127,7 @@ self.__cr_array_1_included = False self.__array_1_registered = set() #(type.decl_string,size) self.__free_operators = [] + self.__exposed_free_fun_overloads = set() def _prepare_decls( self, decls, doc_extractor ): global DO_NOT_REPORT_MSGS @@ -680,15 +681,56 @@ self.curr_code_creator.adopt_creator( maker ) def visit_free_function( self ): - maker = code_creators.free_function_t( function=self.curr_decl ) - self.curr_code_creator.adopt_creator( maker ) + if self.curr_decl in self.__exposed_free_fun_overloads: + return + elif self.curr_decl.use_overload_macro: + parent_decl = self.curr_decl.parent + names = set( map( lambda decl: decl.name + , parent_decl.free_functions( allow_empty=True, recursive=False ) ) ) + for name in names: + overloads = parent_decl.free_functions( name, allow_empty=True, recursive=False ) + overloads = filter( lambda decl: decl.use_overload_macro, overloads ) + if not overloads: + continue + else: + self.__exposed_free_fun_overloads.update( overloads ) + overloads_cls_creator = code_creators.free_fun_overloads_class_t( overloads ) + self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) + + overloads_reg = code_creators.free_fun_overloads_t( overloads_cls_creator ) + self.curr_code_creator.adopt_creator( overloads_reg ) + else: + maker = code_creators.free_function_t( function=self.curr_decl ) + self.curr_code_creator.adopt_creator( maker ) + def visit_free_operator( self ): self.__free_operators.append( self.curr_decl ) def visit_class_declaration(self ): pass + def expose_overloaded_mem_fun_using_macro( self, cls, cls_creator ): + #returns set of exported member functions + exposed = set() + names = set( map( lambda decl: decl.name + , cls.member_functions( allow_empty=True, recursive=False ) ) ) + for name in names: + overloads = cls.member_functions( name, allow_empty=True, recursive=False ) + overloads = filter( lambda decl: decl.use_overload_macro, overloads ) + if not overloads: + continue + else: + exposed.update( overloads ) + + overloads_cls_creator = code_creators.mem_fun_overloads_class_t( overloads ) + self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) + cls_creator.user_declarations.append( overloads_cls_creator ) + + overloads_reg = code_creators.mem_fun_overloads_t( overloads_cls_creator ) + cls_creator.adopt_creator( overloads_reg ) + return exposed + def visit_class(self ): assert isinstance( self.curr_decl, declarations.class_t ) cls_decl = self.curr_decl @@ -720,9 +762,13 @@ tcons = code_creators.null_constructor_wrapper_t( class_inst=self.curr_decl ) wrapper.adopt_creator( tcons ) + exposed = self.expose_overloaded_mem_fun_using_macro( cls_decl, cls_cc ) + cls_parent_cc.adopt_creator( cls_cc ) self.curr_code_creator = cls_cc for decl in exportable_members: + if decl in exposed: + continue self.curr_decl = decl declarations.apply_visitor( self, decl ) Added: pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp (rev 0) +++ pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp 2006-08-30 10:04:41 UTC (rev 495) @@ -0,0 +1,45 @@ +// Copyright 2004 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef __overloads_macro_to_be_exported_hpp__ +#define __overloads_macro_to_be_exported_hpp__ + +namespace overloads_macro{ + +struct calculator_t{ + + double add( int i, int j ){ + return i + j; + } + + double add( int i, int j, int k ){ + return i * j + k; + } + + double add( double i, double j ){ + return i + j; + } + + +}; + +double add( int i, int j ){ + return i + j; +} + +double add( int i, int j, int k ){ + return i * j + k; +} + +double add( double i, double j ){ + return i + j; +} + + + +} + + +#endif//__enums_to_be_exported_hpp__ Added: pyplusplus_dev/unittests/overloads_macro_tester.py =================================================================== --- pyplusplus_dev/unittests/overloads_macro_tester.py (rev 0) +++ pyplusplus_dev/unittests/overloads_macro_tester.py 2006-08-30 10:04:41 UTC (rev 495) @@ -0,0 +1,51 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import sys +import unittest +import fundamental_tester_base + +class tester_t(fundamental_tester_base.fundamental_tester_base_t): + EXTENSION_NAME = 'overloads_macro' + + def __init__( self, *args ): + fundamental_tester_base.fundamental_tester_base_t.__init__( + self + , tester_t.EXTENSION_NAME + , *args ) + + def customize(self, mb ): + calc = mb.class_( 'calculator_t' ) + calc.always_expose_using_scope = True + calc.member_functions( 'add' ).set_use_overload_macro( True ) + add_doubles = calc.member_function( 'add', arg_types=['double', 'double'] ) + add_doubles.set_use_overload_macro( False ) + + mb.free_functions( 'add' ).set_use_overload_macro( True ) + add_doubles = mb.free_function( 'add', arg_types=['double', 'double'] ) + add_doubles.set_use_overload_macro( False ) + + + def run_tests(self, module): + calc = module.calculator_t() + self.failUnless( 3 == calc.add( 1, 2 ) ) + self.failUnless( 9 == calc.add( 3, 2, 3 ) ) + self.failUnless( 3 == calc.add( 1.5, 1.5 ) ) + self.failUnless( 3 == module.add( 1, 2 ) ) + self.failUnless( 9 == module.add( 3, 2, 3 ) ) + self.failUnless( 3 == module.add( 1.5, 1.5 ) ) + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(tester_t)) + return suite + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run( create_suite() ) + +if __name__ == "__main__": + run_suite() Modified: pyplusplus_dev/unittests/test_all.py =================================================================== --- pyplusplus_dev/unittests/test_all.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/unittests/test_all.py 2006-08-30 10:04:41 UTC (rev 495) @@ -60,6 +60,7 @@ import unnamed_classes_tester import cppexceptions_tester import no_init_tester +import overloads_macro_tester def create_suite(times): testers = [ @@ -116,6 +117,7 @@ , unnamed_classes_tester , cppexceptions_tester , no_init_tester + , overloads_macro_tester ] main_suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |