Beispiel #1
0
 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('"', '\\"')))
Beispiel #2
0
 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('"', '\\"')))