Esempio n. 1
0
def is_const_ref(type):
    """ Extra trait tester method to check if something is a const reference. """
    is_const = tt.is_const(type) or (hasattr(type, 'base')
                                     and tt.is_const(type.base))
    is_ref = tt.is_reference(type) or (hasattr(type, 'base')
                                       and tt.is_reference(type.base))
    return (is_ref and is_const)
Esempio n. 2
0
def remove_const_from_reference(type):
    "Helper to avoid compile errors with const-reference-protected-destructor argument types"
    if not type_traits.is_reference(type):
        return type
    nonref = declarations.remove_reference(type)
    if not type_traits.is_const(nonref):
        return type
    nonconst = declarations.remove_const(nonref)
    return cpptypes.reference_t(nonconst)
Esempio n. 3
0
def remove_const_from_reference(type):
    "Helper to avoid compile errors with const-reference-protected-destructor argument types"
    if not type_traits.is_reference(type):
        return type
    nonref = declarations.remove_reference(type)
    if not type_traits.is_const(nonref):
        return type
    nonconst = declarations.remove_const(nonref)
    return cpptypes.reference_t(nonconst)
Esempio n. 4
0
def wrap_const_ref_params(cls):
    """ Find all member functions of cls and if they take a const& to a class
         that does not have a destructor, then create a thin wrapper for them.
         This works around an issue with boost.python where it needs a destructor.
   """
    #[Roman] Obviously, this will only work, if the function does not need other
    #wrapper, I think, this is a new use case for Matthias "arguments policies"
    #functionality.
    calldefs = cls.calldefs()

    if None == calldefs:
        return

    for c in calldefs:
        # Skip constructors
        if isinstance(c, pd.constructor_t):
            continue

        # Find arguments that need replacing
        args_to_replace = [
        ]  # List of indices to args to replace with wrapping
        args = c.arguments
        for i in range(len(args)):
            arg = args[i]
            if is_const_ref(arg.type):
                naked_arg = tt.remove_cv(tt.remove_reference(arg.type))
                if tt.is_class(naked_arg):
                    class_type = naked_arg.declaration
                    if not tt.has_public_destructor(class_type):
                        print "Found indestructible const& arg: [%s]:[%s] " % (
                            str(c), str(arg))
                        args_to_replace.append(i)

        # Now replace arguments
        if len(args_to_replace):
            if isinstance(
                    c, pd.operator_t) and c.symbol in ["<", "==", "!=", "="]:
                c.exclude()
                continue

            new_args = copy.copy(
                args
            )  # Make new copy of args so we don't modify the existing method
            for i in args_to_replace:
                old_arg_type = args[i].type
                if tt.is_reference(old_arg_type) and tt.is_const(
                        old_arg_type.base):
                    new_args[i].type = cpptypes.reference_t(
                        tt.remove_const(old_arg_type.base))
                elif tt.is_const(old_arg):
                    new_args[i].type = tt.remove_const(old_arg_type)

            wrapper_name = "%s_const_ref_wrapper" % c.name
            args_str = [str(a) for a in new_args]
            arg_names_str = [str(a.name) for a in new_args]
            new_sig = "static %s %s(%s& self_arg, %s)" % (
                c.return_type, wrapper_name, pd.full_name(cls),
                ",".join(args_str))
            new_method = """%s
         { return self_arg.%s(%s); }
         """ % (new_sig, c.name, ",".join(arg_names_str))

            # Add it all
            c.exclude()

            #[Roman] you can use cls.add_declaration_code, this could simplify the
            #wrapper you created, because it will generate the code within the source
            #file, the class is generated
            cls.add_declaration_code(new_method)

            cls.add_registration_code('def("%s", &%s)' %
                                      (c.name, wrapper_name),
                                      works_on_instance=True)
Esempio n. 5
0
def wrap_const_ref_params(cls):
   """ Find all member functions of cls and if they take a const& to a class
         that does not have a destructor, then create a thin wrapper for them.
         This works around an issue with boost.python where it needs a destructor.
   """
   #[Roman] Obviously, this will only work, if the function does not need other
   #wrapper, I think, this is a new use case for Matthias "arguments policies"
   #functionality.
   calldefs = cls.calldefs()

   if None == calldefs:
      return

   for c in calldefs:
      # Skip constructors
      if isinstance(c, pd.constructor_t):
         continue

      # Find arguments that need replacing
      args_to_replace = []   # List of indices to args to replace with wrapping
      args = c.arguments
      for i in range(len(args)):
         arg = args[i]
         if is_const_ref(arg.type):
            naked_arg = tt.remove_cv(tt.remove_reference(arg.type))
            if tt.is_class(naked_arg):
               class_type = naked_arg.declaration
               if not tt.has_public_destructor(class_type):
                  print "Found indestructible const& arg: [%s]:[%s] "%(str(c), str(arg))
                  args_to_replace.append(i)

      # Now replace arguments
      if len(args_to_replace):
         if isinstance(c, pd.operator_t) and c.symbol in ["<","==","!=","="]:
            c.exclude()
            continue

         new_args = copy.copy(args)   # Make new copy of args so we don't modify the existing method
         for i in args_to_replace:
            old_arg_type = args[i].type
            if tt.is_reference(old_arg_type) and tt.is_const(old_arg_type.base):
               new_args[i].type = cpptypes.reference_t(tt.remove_const(old_arg_type.base))
            elif tt.is_const(old_arg):
               new_args[i].type = tt.remove_const(old_arg_type)

         wrapper_name = "%s_const_ref_wrapper"%c.name
         args_str = [str(a) for a in new_args]
         arg_names_str = [str(a.name) for a in new_args]
         new_sig = "static %s %s(%s& self_arg, %s)"%(c.return_type,
                                                     wrapper_name,
                                                     pd.full_name(cls),
                                                     ",".join(args_str))
         new_method = """%s
         { return self_arg.%s(%s); }
         """%(new_sig,c.name,",".join(arg_names_str))

         # Add it all
         c.exclude()
         
         #[Roman] you can use cls.add_declaration_code, this could simplify the
         #wrapper you created, because it will generate the code within the source
         #file, the class is generated
         cls.add_declaration_code(new_method)
         
         cls.add_registration_code('def("%s", &%s)'%(c.name, wrapper_name), 
                                   works_on_instance=True)
Esempio n. 6
0
def is_const_ref(type):
   """ Extra trait tester method to check if something is a const reference. """
   is_const = tt.is_const(type) or (hasattr(type,'base') and tt.is_const(type.base))
   is_ref = tt.is_reference(type) or (hasattr(type,'base') and tt.is_reference(type.base))
   return (is_ref and is_const)