From 5e190eb42e3c9875412fb35e821cd1d7a9b6db1e Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Sun, 31 May 2020 13:43:32 -0400 Subject: [PATCH] Fix stack overflow when overriding wx.CustomObject.SetData In the implementation of wx.CustomData.SetData, we need to check the sipSelfWasArg variable to determine whether to call the parent class implementation of SetData. To do this, we switched to using addCppMethod_sip which allows us to access the sipSelfWasArg variable. The sip generator stuff for CppMethod_sip needed some additions to match the behavior of CppMethod. --- etg/dataobj.py | 4 ++-- etgtools/sip_generator.py | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/etg/dataobj.py b/etg/dataobj.py index 50b05f91..24201d25 100644 --- a/etg/dataobj.py +++ b/etg/dataobj.py @@ -340,11 +340,11 @@ def run(): body="return wxPyMakeBuffer(self->GetData(), self->GetSize());") c.find('SetData').ignore() - c.addCppMethod('bool', 'SetData', '(wxPyBuffer* buf)', + c.addCppMethod_sip('bool', 'SetData', '(wxPyBuffer* buf)', cppSignature='bool (size_t len, const void* buf)', isVirtual=True, doc="Copies data from the provided buffer to this data object's buffer", - body="return self->SetData(buf->m_len, buf->m_ptr);") + body="sipRes = (sipSelfWasArg ? sipCpp-> ::wxCustomDataObject::SetData(buf->m_len, buf->m_ptr) : sipCpp->SetData(buf->m_len, buf->m_ptr));") addGetAllFormats(c) addBaseVirtuals(c) diff --git a/etgtools/sip_generator.py b/etgtools/sip_generator.py index f6865c36..f8c7ed94 100644 --- a/etgtools/sip_generator.py +++ b/etgtools/sip_generator.py @@ -908,16 +908,30 @@ from .%s import * assert isinstance(method, extractors.CppMethodDef_sip) if method.ignored: return + _needDocstring = getattr(method, '_needDocstring', True) cppSig = " [ %s ]" % method.cppSignature if method.cppSignature else "" if method.isCtor: stream.write('%s%s%s%s%s;\n' % (indent, method.name, method.argsString, self.annotate(method), cppSig)) else: - stream.write('%s%s %s%s%s%s;\n' % - (indent, method.type, method.name, method.argsString, + virtual = "virtual " if method.isVirtual else "" + stream.write('%s%s%s %s%s%s%s;\n' % + (indent, virtual, method.type, method.name, method.argsString, self.annotate(method), cppSig)) + # write the docstring + if _needDocstring and not (method.isCtor or method.isDtor): + self.generateDocstring(method, stream, indent) + # We only write a docstring for the first overload, otherwise + # SIP appends them all together. + _needDocstring = False stream.write('%s%%MethodCode\n' % indent) + if not (method.isCtor and method.isDtor): + stream.write('%sPyErr_Clear();\n' % (indent+' '*4)) + stream.write('%sPy_BEGIN_ALLOW_THREADS\n' % (indent+' '*4)) stream.write(nci(method.body, len(indent)+4)) + if not (method.isCtor and method.isDtor): + stream.write('%sPy_END_ALLOW_THREADS\n' % (indent+' '*4)) + stream.write('%sif (PyErr_Occurred()) sipIsErr = 1;\n' % (indent+' '*4)) stream.write('%s%%End\n\n' % indent)