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 testCallableType(self): t = types.CallableType('cname::cpp_type', '(x:py)->None', 'lambda_Name_def') header = '\n'.join(t.GenHeader()) + '\n' self.assertMultiLineEqual(header, textwrap.dedent("""\ // (x:py)->None PyObject* Clif_PyObjFrom(cname::cpp_type, py::PostConv); """))
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))