def generate_python_call(self): """code to call the python method""" if settings._get_deprecated_virtuals(): params = ["m_pyself", '(char *) "_%s"' % self.method_name] else: params = ["m_pyself", '(char *) "%s"' % self.method_name] build_params = self.build_params.get_parameters() if build_params[0][0] == '"': build_params[0] = "(char *) " + build_params[0] params.extend(build_params) self.before_call.write_code("py_retval = PyObject_CallMethod(%s);" % (", ".join(params),)) self.before_call.write_error_check("py_retval == NULL", failure_cleanup="PyErr_Print();") self.before_call.add_cleanup_code("Py_DECREF(py_retval);")
def generate_python_call(self): """code to call the python method""" if settings._get_deprecated_virtuals(): params = ['m_pyself', '(char *) "_%s"' % self.method_name] else: params = ['m_pyself', '(char *) "%s"' % self.method_name] build_params = self.build_params.get_parameters() if build_params[0][0] == '"': build_params[0] = '(char *) ' + build_params[0] params.extend(build_params) self.before_call.write_code('py_retval = PyObject_CallMethod(%s);' % (', '.join(params), )) self.before_call.write_error_check('py_retval == NULL', failure_cleanup='PyErr_Print();') self.before_call.add_cleanup_code('Py_DECREF(py_retval);')
def generate_call(self, class_=None): "virtual method implementation; do not call" # assert isinstance(class_, CppClass) if class_ is None: class_ = self._class if self.template_parameters: template_params = "< %s >" % ", ".join(self.template_parameters) else: template_params = "" if self.return_value.ctype == "void": retval_assign = "" else: if self.return_value.REQUIRES_ASSIGNMENT_CONSTRUCTOR: retval_assign = "%s retval = " % (self.return_value.ctype,) else: retval_assign = "retval = " if ( class_.helper_class is not None and self.is_virtual and not self.is_pure_virtual and not settings._get_deprecated_virtuals() ): helper = self.before_call.declare_variable( type_="%s *" % class_.helper_class.name, name="helper_class", initializer=("dynamic_cast<%s*> (self->obj)" % class_.helper_class.name), ) else: helper = None if self.is_static: method = "%s::%s%s" % (class_.full_name, self.method_name, template_params) else: method = "self->obj->%s%s" % (self.method_name, template_params) if self.throw: self.before_call.write_code("try\n{") self.before_call.indent() if self.is_static: self.before_call.write_code( retval_assign + ("%s::%s%s(%s);" % (class_.full_name, self.method_name, template_params, ", ".join(self.call_params))) ) else: if helper is None: self.before_call.write_code( retval_assign + ("self->obj->%s%s(%s);" % (self.method_name, template_params, ", ".join(self.call_params))) ) else: self.before_call.write_code( retval_assign + ( "(%s == NULL)? (self->obj->%s%s(%s)) : (self->obj->%s::%s%s(%s));" % ( helper, self.method_name, template_params, ", ".join(self.call_params), class_.full_name, self.method_name, template_params, ", ".join(self.call_params), ) ) ) if self.throw: for exc in self.throw: self.before_call.unindent() self.before_call.write_code("} catch (%s const &exc) {" % exc.full_name) self.before_call.indent() self.before_call.write_cleanup() exc.write_convert_to_python(self.before_call, "exc") self.before_call.write_code("return NULL;") self.before_call.unindent() self.before_call.write_code("}")
def generate(self, code_sink): """generates the proxy virtual method""" if self.method.is_const: decl_post_modifiers = ["const"] else: decl_post_modifiers = [] if self.method.throw: decl_post_modifiers.append("throw (%s)" % (", ".join([ex.full_name for ex in self.method.throw]),)) ## if the python subclass doesn't define a virtual method, ## just chain to parent class and don't do anything else call_params = ", ".join([param.name for param in self.parameters]) py_method = self.declarations.declare_variable("PyObject*", "py_method") if settings._get_deprecated_virtuals(): self.before_call.write_code( '%s = PyObject_GetAttrString(m_pyself, (char *) "_%s"); PyErr_Clear();' % (py_method, self.method_name) ) else: self.before_call.write_code( '%s = PyObject_GetAttrString(m_pyself, (char *) "%s"); PyErr_Clear();' % (py_method, self.method_name) ) self.before_call.add_cleanup_code("Py_XDECREF(%s);" % py_method) self.before_call.write_code(r"if (%s == NULL || %s->ob_type == &PyCFunction_Type) {" % (py_method, py_method)) if self.return_value.ctype == "void": if not (self.method.is_pure_virtual or self.method.visibility == "private"): self.before_call.write_code(r" %s::%s(%s);" % (self.class_.full_name, self.method_name, call_params)) self.before_call.write_cleanup() self.before_call.write_code(r" return;") else: if self.method.is_pure_virtual or self.method.visibility == "private": if ( isinstance(self.return_value, cppclass.CppClassReturnValue) and self.return_value.cpp_class.has_trivial_constructor ): pass else: self.set_error_return( """ PyErr_Print(); Py_FatalError("Error detected, but parent virtual is pure virtual or private virtual, " "and return is a class without trival constructor");""" ) else: self.set_error_return("return %s::%s(%s);" % (self.class_.full_name, self.method_name, call_params)) self.before_call.indent() self.before_call.write_cleanup() self.before_call.write_code(self.error_return) self.before_call.unindent() self.before_call.write_code("}") ## Set "m_pyself->obj = this" around virtual method call invocation self_obj_before = self.declarations.declare_variable("%s*" % self.class_.full_name, "self_obj_before") self.before_call.write_code( "%s = reinterpret_cast< %s* >(m_pyself)->obj;" % (self_obj_before, self.class_.pystruct) ) if self.method.is_const: this_expression = "const_cast< %s* >((const %s*) this)" % (self.class_.full_name, self.class_.full_name) else: this_expression = "(%s*) this" % (self.class_.full_name) self.before_call.write_code( "reinterpret_cast< %s* >(m_pyself)->obj = %s;" % (self.class_.pystruct, this_expression) ) self.before_call.add_cleanup_code( "reinterpret_cast< %s* >(m_pyself)->obj = %s;" % (self.class_.pystruct, self_obj_before) ) super(CppVirtualMethodProxy, self).generate( code_sink, "::".join((self._helper_class.name, self.method_name)), decl_modifiers=[], decl_post_modifiers=decl_post_modifiers, )
def generate_call(self, class_=None): "virtual method implementation; do not call" #assert isinstance(class_, CppClass) if class_ is None: class_ = self._class if self.template_parameters: template_params = '< %s >' % ', '.join(self.template_parameters) else: template_params = '' if self.return_value.ctype == 'void': retval_assign = '' else: if self.return_value.REQUIRES_ASSIGNMENT_CONSTRUCTOR: retval_assign = '%s retval = ' % (self.return_value.ctype, ) else: retval_assign = 'retval = ' if class_.helper_class is not None and self.is_virtual and not self.is_pure_virtual\ and not settings._get_deprecated_virtuals(): helper = self.before_call.declare_variable( type_="%s *" % class_.helper_class.name, name="helper_class", initializer=("dynamic_cast<%s*> (self->obj)" % class_.helper_class.name)) else: helper = None if self.is_static: method = '%s::%s%s' % (class_.full_name, self.method_name, template_params) else: method = 'self->obj->%s%s' % (self.method_name, template_params) if self.throw: self.before_call.write_code('try\n{') self.before_call.indent() if self.is_static: self.before_call.write_code(retval_assign + ( '%s::%s%s(%s);' % (class_.full_name, self.method_name, template_params, ", ".join(self.call_params)))) else: if helper is None: self.before_call.write_code( retval_assign + ('self->obj->%s%s(%s);' % (self.method_name, template_params, ", ".join(self.call_params)))) else: self.before_call.write_code(retval_assign + ( '(%s == NULL)? (self->obj->%s%s(%s)) : (self->obj->%s::%s%s(%s));' % (helper, self.method_name, template_params, ", ".join( self.call_params), class_.full_name, self.method_name, template_params, ", ".join(self.call_params)))) if self.throw: for exc in self.throw: self.before_call.unindent() self.before_call.write_code('} catch (%s const &exc) {' % exc.full_name) self.before_call.indent() self.before_call.write_cleanup() exc.write_convert_to_python(self.before_call, 'exc') self.before_call.write_code('return NULL;') self.before_call.unindent() self.before_call.write_code('}')
def generate(self, code_sink): """generates the proxy virtual method""" if self.method.is_const: decl_post_modifiers = ['const'] else: decl_post_modifiers = [] if self.method.throw: decl_post_modifiers.append( "throw (%s)" % (', '.join([ex.full_name for ex in self.method.throw]), )) ## if the python subclass doesn't define a virtual method, ## just chain to parent class and don't do anything else call_params = ', '.join([param.name for param in self.parameters]) py_method = self.declarations.declare_variable('PyObject*', 'py_method') if settings._get_deprecated_virtuals(): self.before_call.write_code( '%s = PyObject_GetAttrString(m_pyself, (char *) "_%s"); PyErr_Clear();' % (py_method, self.method_name)) else: self.before_call.write_code( '%s = PyObject_GetAttrString(m_pyself, (char *) "%s"); PyErr_Clear();' % (py_method, self.method_name)) self.before_call.add_cleanup_code('Py_XDECREF(%s);' % py_method) self.before_call.write_code( r'if (%s == NULL || %s->ob_type == &PyCFunction_Type) {' % (py_method, py_method)) if self.return_value.ctype == 'void': if not (self.method.is_pure_virtual or self.method.visibility == 'private'): self.before_call.write_code( r' %s::%s(%s);' % (self.class_.full_name, self.method_name, call_params)) self.before_call.write_cleanup() self.before_call.write_code(r' return;') else: if self.method.is_pure_virtual or self.method.visibility == 'private': if isinstance(self.return_value, cppclass.CppClassReturnValue) \ and self.return_value.cpp_class.has_trivial_constructor: pass else: self.set_error_return(''' PyErr_Print(); Py_FatalError("Error detected, but parent virtual is pure virtual or private virtual, " "and return is a class without trival constructor");''') else: self.set_error_return( "return %s::%s(%s);" % (self.class_.full_name, self.method_name, call_params)) self.before_call.indent() self.before_call.write_cleanup() self.before_call.write_code(self.error_return) self.before_call.unindent() self.before_call.write_code('}') ## Set "m_pyself->obj = this" around virtual method call invocation self_obj_before = self.declarations.declare_variable( '%s*' % self.class_.full_name, 'self_obj_before') self.before_call.write_code( "%s = reinterpret_cast< %s* >(m_pyself)->obj;" % (self_obj_before, self.class_.pystruct)) if self.method.is_const: this_expression = ("const_cast< %s* >((const %s*) this)" % (self.class_.full_name, self.class_.full_name)) else: this_expression = "(%s*) this" % (self.class_.full_name) self.before_call.write_code( "reinterpret_cast< %s* >(m_pyself)->obj = %s;" % (self.class_.pystruct, this_expression)) self.before_call.add_cleanup_code( "reinterpret_cast< %s* >(m_pyself)->obj = %s;" % (self.class_.pystruct, self_obj_before)) super(CppVirtualMethodProxy, self).generate(code_sink, '::'.join( (self._helper_class.name, self.method_name)), decl_modifiers=[], decl_post_modifiers=decl_post_modifiers)