def _CreateInputParameter(func_name, ast_param, arg, args): """Return a string to create C++ stack var named arg. args += arg getter.""" ptype = ast_param.type ctype = ptype.cpp_type smartptr = (ctype.startswith('::std::unique_ptr') or ctype.startswith('::std::shared_ptr')) # std::function special case if not ctype: assert ptype.callable, 'Non-callable param has empty cpp_type' if len(ptype.callable.returns) > 1: raise ValueError('Callbacks may not have any output parameters, ' '%s param %s has %d' % (func_name, ast_param.name.native, len(ptype.callable.returns) - 1)) args.append('std::move(%s)' % arg) return 'std::function<%s> %s;' % (astutils.StdFuncParamStr( ptype.callable), arg) # T* if ptype.cpp_raw_pointer: if ptype.cpp_toptr_conversion: args.append(arg) return '%s %s;' % (ctype, arg) t = ctype[:-1] if ctype.endswith('*'): if ptype.cpp_abstract: if ptype.cpp_touniqptr_conversion: args.append(arg + '.get()') return '::std::unique_ptr<%s> %s;' % (t, arg) elif ptype.cpp_has_public_dtor: # Create a copy on stack and pass its address. if ptype.cpp_has_def_ctor: args.append('&' + arg) return '%s %s;' % (t, arg) else: args.append('&%s.value()' % arg) return '::gtl::optional<%s> %s;' % (t, arg) raise TypeError("Can't convert %s to %s" % (ptype.lang_type, ctype)) if (smartptr or ptype.cpp_abstract) and not ptype.cpp_touniqptr_conversion: raise TypeError( 'Can\'t create "%s" variable (C++ type %s) in function %s' ', no valid conversion defined' % (ast_param.name.native, ctype, func_name)) # unique_ptr<T>, shared_ptr<T> if smartptr: args.append('std::move(%s)' % arg) return '%s %s;' % (ctype, arg) # T, [const] T& if ptype.cpp_toptr_conversion: args.append('*' + arg) return '%s* %s;' % (ctype, arg) if ptype.cpp_abstract: # for AbstractType & args.append('*' + arg) return 'std::unique_ptr<%s> %s;' % (ctype, arg) # Create a copy on stack (even fot T&, most cases should have to_T* conv). if ptype.cpp_has_def_ctor: args.append('std::move(%s)' % arg) return '%s %s;' % (ctype, arg) else: args.append(arg + '.value()') return '::gtl::optional<%s> %s;' % (ctype, arg)
def WrapCallable(self, c, fname, retnum, line_number): """Process callable return type AST.Type c.""" assert c.HasField('callable'), ('WrapCallable called on AST that has no' ' "callable":\n' + str(c)) cname = Ident(c.callable.name.cpp_name) or fname+'_ret%d_lambda' % retnum wname = 'lambda_'+cname for i, r in enumerate(c.callable.returns): if r.type.HasField('callable'): for s in self.WrapCallable(r.type, cname, i, line_number): yield s if not c.cpp_type: assert c.callable, 'Non-callable param has empty cpp_type' c.cpp_type = 'std::function<%s>' % astutils.StdFuncParamStr(c.callable) for s in gen.FunctionCall( '', wname, doc=c.lang_type, catch=self.catch_cpp_exceptions and not c.callable.cpp_noexcept, call=['void* fp = PyCapsule_GetPointer(self, typeid(%s).name());' % c.cpp_type, 'if (fp == nullptr) return nullptr;', '(*static_cast<%s*>(fp))' % c.cpp_type], postcall_init=None, typepostconversion=self.typemap, func_ast=c.callable, lineno=line_number): yield s defname = wname + '_def' yield gen.FromFunctionDef(c.cpp_type, defname, wname, VARARGS if len(c.callable.params) else NOARGS, 'Calls '+c.cpp_type) self.types.add(types.CallableType(c.cpp_type, c.lang_type, defname))
def WrapOneCallable(self, c, fname, ret_or_arg, line_number, class_ns, only_pyobjas): """Process callable return or param type of AST.Type c.""" assert c.HasField('callable'), ( 'WrapOneCallable called on AST that has no' ' "callable":\n' + str(c)) cname = Ident( c.callable.name.cpp_name) or fname + '_%s_lambda' % ret_or_arg wname = 'lambda_' + cname for s in self._WrapAllCallables(c.callable, cname, line_number, class_ns, not only_pyobjas): yield s if only_pyobjas is ret_or_arg.startswith('ret'): # Clif_PyObjFrom() for this callable is not needed (only Clif_PyObjAs()). return if not c.cpp_type: assert c.callable, 'Non-callable param has empty cpp_type' c.cpp_type = 'std::function<%s>' % astutils.StdFuncParamStr( c.callable) if c.cpp_type in self.types_std_function_cpp_types: return self.types_std_function_cpp_types.add(c.cpp_type) for s in gen.FunctionCall( '', wname, doc=c.lang_type, catch=self.catch_cpp_exceptions and not c.callable.cpp_noexcept, call=[ 'void* fp = PyCapsule_GetPointer(self, typeid(%s).name());' % c.cpp_type, 'if (fp == nullptr) return nullptr;', '(*static_cast<%s*>(fp))' % c.cpp_type ], postcall_init=None, typepostconversion=self.typemap, func_ast=c.callable, lineno=line_number): yield s defname = wname + '_def' yield '' yield gen.FromFunctionDef( c.cpp_type, defname, wname, VARARGS if len(c.callable.params) else NOARGS, 'Calls ' + c.cpp_type) if class_ns: defname = class_ns + '::' + defname self.types.append(types.CallableType(c.cpp_type, c.lang_type, defname))