def WrapFunc(self, f, ln, unused_ns, class_ns=''): """Process AST.FuncDecl f.""" cname = Ident(f.name.cpp_name) assert cname, 'cpp_name is empty for ' + f.name.native pyname = f.name.native.rstrip('#') if pyname.endswith('@'): ctxmgr = pyname pyname = pyname[:-1] else: ctxmgr = None if self.nested and cname.startswith('operator'): wrapper_name = 'wrap' + pyname elif pyname == '__init__': wrapper_name = 'wrap' + types.Mangle(self.name) + '_as___init__' else: wrapper_name = 'wrap' + types.Mangle(cname) if pyname != cname: wrapper_name += '_as_' + pyname if f.ignore_return_value: assert len( f.returns) < 2, ('Func with ignore_return_value has too many' ' returns (%d)' % len(f.returns)) del f.returns[:] for s in self._WrapAllCallables(f, cname, ln, class_ns, False): yield s if f.cpp_opfunction or (f.is_extend_method and not f.classmethod and not f.constructor): self_param = f.params.pop(0) else: self_param = None if ctxmgr: assert not f.classmethod, "Context manager methods can't be static" # Force context manager args API. meth = VARARGS if ctxmgr == '__exit__@' else NOARGS else: meth = VARARGS if len(f.params) else NOARGS for s in gen.FunctionCall( # Keep '@' in method name to distinguish a ctxmgr. f.name.native.rstrip('#'), wrapper_name, func_ast=f, lineno=ln, call=self._FunctionCallExpr(f, cname, pyname), doc=next(astutils.Docstring(f)), prepend_self=self_param, catch=self.catch_cpp_exceptions and not f.cpp_noexcept, postcall_init=None, typepostconversion=self.typemap): yield s if f.classmethod: meth += ' | METH_CLASS' # Keep '#' in method name to distinguish map/seq slots. self.methods.append( (f.name.native.rstrip('@'), wrapper_name, meth, '\\n'.join(astutils.Docstring(f)).replace('"', '\\"')))
def WrapFunc(self, f, ln, unused_ns): """Process AST.FuncDecl f.""" cname = Ident(f.name.cpp_name) assert cname pyname = f.name.native.rstrip('#') if pyname.endswith('@'): ctxmgr = pyname pyname = pyname[:-1] else: ctxmgr = None if self.nested and cname.startswith('operator'): wrapper_name = 'wrap' + pyname elif pyname == '__init__': wrapper_name = 'wrap' + types.Mangle(self.name) + '_as___init__' else: wrapper_name = 'wrap' + types.Mangle(cname) if pyname != cname: wrapper_name += '_as_' + pyname if f.ignore_return_value: assert len( f.returns) < 2, ('Func with ignore_return_value has too many' ' returns (%d)' % len(f.returns)) del f.returns[:] for i, r in enumerate(f.returns): if r.type.HasField('callable'): for s in (self.WrapCallable(r.type, cname, i, ln)): yield s self_param = f.params.pop(0) if f.cpp_opfunction else None if ctxmgr: assert not f.classmethod, "Context manager methods can't be static" # Force context manager args API. meth = VARARGS if ctxmgr == '__exit__@' else NOARGS else: meth = VARARGS if len(f.params) else NOARGS call = f.name.cpp_name postcall = None if self.nested and not f.classmethod: cpp = 'reinterpret_cast<%s*>(self)->cpp' % self.wrapper_class_name if f.constructor: assert not f.returns, cname + ' ctor must return void' if f.virtual: ctor = VIRTUAL_OVERRIDER_CLASS postcall = '->::clif::PyObj::Init(self);' else: ctor = self.fqname if pyname == '__init__': call = '%s = ::clif::MakeShared<%s>' % (cpp, ctor) if postcall: postcall = cpp + postcall # C++ constructors do not return anything. f.cpp_void_return = True else: # additional ctors f.classmethod = True call = '::gtl::MakeUnique<%s>' % ctor # Pretend we're returning a new instance. r = f.returns.add() r.type.lang_type = self.pyname r.type.cpp_type = 'std::unique_ptr<%s>' % ctor f.cpp_void_return = False elif not f.cpp_opfunction: if self.final: call = cpp + '->' + cname else: call = [ '%s* c = ThisPtr(self);' % self.fqname, 'if (!c) return nullptr;', ] if f.virtual: call.append('c->' + self.name + '::' + cname) else: call.append('c->' + cname) for s in ( # Keep '@' in method name to distinguish ctxmgr. gen.FunctionCall(f.name.native.rstrip('#'), wrapper_name, doc=next(astutils.Docstring(f)), catch=self.catch_cpp_exceptions and not f.cpp_noexcept, call=call, postcall_init=postcall, lineno=ln, prepend_self=self_param, typepostconversion=self.typemap, func_ast=f)): yield s if f.classmethod: meth += ' | METH_CLASS' # Keep '#' in method name to distinguish map/seq slots. self.methods.append( (f.name.native.rstrip('@'), wrapper_name, meth, '\\n'.join(astutils.Docstring(f)).replace('"', '\\"')))