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.
|