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