pyplusplus.code_creators.calldef_utils

Package pyplusplus :: Package code_creators :: Module calldef_utils |

# Source Code for Module pyplusplus.code_creators.calldef_utils

      1  # Copyright 2004-2008 Roman Yakovenko
      2  # Distributed under the Boost Software License, Version 1.0. (See
      3  # accompanying file LICENSE_1_0.txt or copy at
      4  # http://www.boost.org/LICENSE_1_0.txt)
      5
      6  import os
      7  import algorithm
      8  import code_creator
      9  from pygccxml import declarations
     10  from pyplusplus import decl_wrappers
     11  #virtual functions that returns const reference to something
     12  #could not be overriden by Python. The reason is simple:
     13  #in boost::python::override::operator(...) result of marshaling
     14  #(Python 2 C++) is saved on stack, after functions returns the result
     15  #will be reference to no where - access violetion.
     16  #For example see temporal variable tester
     17
     18  use_enum_workaround = False
     19
     20 -class argument_utils_t:
     21
     22      PARAM_SEPARATOR = code_creator.code_creator_t.PARAM_SEPARATOR
     23
     24 -    def __init__( self, declaration, identifier_creator, arguments=None ):
     25          self.__decl = declaration
     26          if None is arguments:
     27              arguments = self.__decl.arguments
     28          self.__args = arguments
     29          self.__id_creator = identifier_creator
     30
     31 -    def __should_use_enum_wa( self, arg ):
     32          global use_enum_workaround
     33          if not declarations.is_enum( arg.type ):
     34              return False
     35          if use_enum_workaround:
     36              return True
     37          #enum belongs to the class we are working on
     38          if self.__decl.parent is declarations.enum_declaration( arg.type ).parent \
     39             and isinstance( self.__decl, declarations.constructor_t ):
     40              return True
     41          return False
     42
     43 -    def keywords_args(self):
     44          if not self.__args:
     45              return ''
     46          boost_arg = self.__id_creator( '::boost::python::arg' )
     47          boost_obj = self.__id_creator( '::boost::python::object' )
     48          result = ['( ']
     49          for arg in self.__args:
     50              if 1 < len( result ):
     51                  result.append( self.PARAM_SEPARATOR )
     52              result.append( boost_arg )
     53              result.append( '("%s")' % arg.name )
     54              if self.__decl.use_default_arguments and arg.default_value:
     55                  if not declarations.is_pointer( arg.type ) or arg.default_value != '0':
     56                      arg_type_no_alias = declarations.remove_alias( arg.type )
     57                      if declarations.is_fundamental( arg_type_no_alias ) \
     58                         and declarations.is_integral( arg_type_no_alias ) \
     59                         and not arg.default_value.startswith( arg_type_no_alias.decl_string ):
     60                          result.append( '=(%s)(%s)' % ( arg_type_no_alias.partial_decl_string
     61                                                         , arg.default_value ) )
     62                      elif self.__should_use_enum_wa( arg ):
     63                          #Work around for bug/missing functionality in boost.python.
     64                          #registration order
     65                          result.append( '=(long)(%s)' % arg.default_value )
     66                      else:
     67                          result.append( '=%s' % arg.default_value )
     68                  else:
     69                      result.append( '=%s()' % boost_obj )
     70          result.append( ' )' )
     71          return ''.join( result )
     72
     73 -    def argument_name( self, index ):
     74          arg = self.__args[ index ]
     75          if arg.name:
     76              return arg.name
     77          else:
     78              return 'p%d' % index
     79
     80 -    def args_declaration( self ):
     81          args = []
     82          for index, arg in enumerate( self.__args ):
     83              result = arg.type.partial_decl_string + ' ' + self.argument_name(index)
     84              if arg.default_value:
     85                  result += '=%s' % arg.default_value
     86              args.append( result )
     87          if len( args ) == 1:
     88              return args[ 0 ]
     89          return self.PARAM_SEPARATOR.join( args )
     90
     91 -    def call_args( self ):
     92          params = []
     93          for index, arg in enumerate( self.__args ):
     94              params.append( decl_wrappers.python_traits.call_traits( arg.type )
     95                             % self.argument_name( index ) )
     96          return ', '.join( params )
     97
     98 -class return_stmt_creator_t( object ):
     99 -    def __init__( self, creator, controller, result_var, return_vars ):
    100          object.__init__( self )
    101          self.__creator = creator
    102          self.__controller = controller
    103          self.__function = controller.function
    104          self.__return_vars = return_vars[:]
    105          self.__pre_return_code = None
    106          self.__return_stmt = None
    107          self.__result_var = result_var
    108          self.__call_policy_alias = controller.register_variable_name( 'call_policies_t' )
    109
    110      @property
    111 -    def pre_return_code( self ):
    112          if None is self.__pre_return_code:
    113              if declarations.is_void( self.__function.return_type ) \
    114                 and ( self.__function.call_policies.is_default() \
    115                       or False == bool( self.__controller.return_variables ) ):
    116                  self.__pre_return_code = ''
    117              elif self.__function.call_policies.is_default():
    118                  self.__pre_return_code = ''
    119              else:
    120                  c_p_typedef = 'typedef %s %s;' \
    121                                % ( self.__function.call_policies.create_template_arg( self.__creator )
    122                                    , self.__call_policy_alias )
    123                  self.__pre_return_code = c_p_typedef
    124          return self.__pre_return_code
    125
    126      @property
    127 -    def statement( self ):
    128          if None is self.__return_stmt:
    129              stmt = ''
    130              bpl_object = algorithm.create_identifier( self.__creator, 'boost::python::object' )
    131              make_tuple = algorithm.create_identifier( self.__creator, 'boost::python::make_tuple' )
    132              make_object = algorithm.create_identifier( self.__creator, 'pyplusplus::call_policies::make_object' )
    133
    134              if not declarations.is_void( self.__function.return_type ):
    135                  if self.__function.call_policies.is_default():
    136                      self.__return_vars.insert( 0, self.__result_var.name )
    137                  else:
    138                      self.__return_vars.insert( 0
    139                              , declarations.call_invocation.join(
    140                                  declarations.templates.join( make_object
    141                                                              , [self.__call_policy_alias, self.__result_var.type.decl_string] )
    142                                  , [self.__result_var.name] ) )
    143
    144              if 0 == len( self.__return_vars ):
    145                  pass
    146              elif 1 == len( self.__return_vars ):
    147                  stmt = bpl_object + '( %s )' % self.__return_vars[ 0 ]
    148              else: # 1 <
    149                  stmt = declarations.call_invocation.join( make_tuple, self.__return_vars )
    150                  if self.__creator.LINE_LENGTH < len( stmt ):
    151                      stmt = declarations.call_invocation.join(
    152                                    make_tuple
    153                                  , self.__return_vars
    154                                  , os.linesep + self.__creator.indent( self.__creator.PARAM_SEPARATOR, 6 ) )
    155
    156              if stmt:
    157                  stmt = 'return ' + stmt + ';'
    158              self.__return_stmt = stmt
    159          return self.__return_stmt
    160