Troubleshooting sip assignHelper != NULL assertion
Scott Talbert
swt at techie.net
Sun May 31 01:23:57 BST 2020
On Sat, 30 May 2020, Phil Thompson wrote:
> On 28/05/2020 16:52, Scott Talbert wrote:
>> On Thu, 28 May 2020, Phil Thompson wrote:
>>
>>> On 28/05/2020 16:30, Scott Talbert wrote:
>>>> On Thu, 28 May 2020, Phil Thompson wrote:
>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I'm running into the following assertion in wxPython that I don't
>>>>>>>> quite understand:
>>>>>>>>
>>>>>>>> python3: ../../../../sip/siplib/siplib.c:3444: parseResult: Assertion
>>>>>>>> `assign_helper != NULL' failed.
>>>>>>>>
>>>>>>>> This is the relevant C++ class:
>>>>>>>>
>>>>>>>> class wxPGWindowList
>>>>>>>> {
>>>>>>>> public:
>>>>>>>> wxPGWindowList(wxWindow* primary, wxWindow* secondary = NULL)
>>>>>>>> : m_primary(primary)
>>>>>>>> , m_secondary(secondary)
>>>>>>>> {
>>>>>>>> }
>>>>>>>>
>>>>>>>> void SetSecondary(wxWindow* secondary) { m_secondary = secondary;
>>>>>>>> }
>>>>>>>>
>>>>>>>> wxWindow* GetPrimary() const { return m_primary; }
>>>>>>>> wxWindow* GetSecondary() const { return m_secondary; }
>>>>>>>>
>>>>>>>> wxWindow* m_primary;
>>>>>>>> wxWindow* m_secondary;
>>>>>>>> };
>>>>>>>
>>>>>>> It doesn't matter what the C++ class looks like, it's the
>>>>>>> corresponding .sip that would be of interest.
>>>>>>
>>>>>> My bad, here it is:
>>>>>> class wxPGWindowList
>>>>>> {
>>>>>> %Docstring
>>>>>> PGWindowList(primary, secondary=None)
>>>>>>
>>>>>> Contains a list of editor windows returned by CreateControls.
>>>>>> %End
>>>>>> %TypeHeaderCode
>>>>>> #include <wx/propgrid/editors.h>
>>>>>> %End
>>>>>>
>>>>>> public:
>>>>>> wxPGWindowList(
>>>>>> wxWindow * primary,
>>>>>> wxWindow * secondary = NULL
>>>>>> );
>>>>>>
>>>>>> void SetSecondary(
>>>>>> wxWindow * secondary
>>>>>> );
>>>>>> %Docstring
>>>>>> SetSecondary(secondary)
>>>>>> %End
>>>>>>
>>>>>> wxWindow * GetPrimary() const;
>>>>>> %Docstring
>>>>>> GetPrimary() -> wx.Window
>>>>>>
>>>>>> Gets window of primary editor.
>>>>>> %End
>>>>>>
>>>>>> wxWindow * GetSecondary() const;
>>>>>> %Docstring
>>>>>> GetSecondary() -> wx.Window
>>>>>>
>>>>>> Gets window of secondary editor.
>>>>>> %End
>>>>>>
>>>>>> public:
>>>>>>
>>>>>>
>>>>>> %Property(name=Primary, get=GetPrimary)
>>>>>> %Property(name=Secondary, get=GetSecondary, set=SetSecondary)
>>>>>> }; // end of class wxPGWindowList
>>>>>>
>>>>>>
>>>>>>>> The assertion occurs when trying to return an instance of
>>>>>>>> wxPGWindowList in a Python method, e.g.:
>>>>>>>>
>>>>>>>> def foo():
>>>>>>>> return wxpg.PGWindowList(a, b)
>>>>>>>>
>>>>>>>> From what I can tell, there is no assignment helper assigned by sip
>>>>>>>> because there is no default constructor? I may be missing something,
>>>>>>>> but I can't see why a default constructor would be needed.
>>>>>>>
>>>>>>> You don't say what version of the sip module you are using but I'm
>>>>>>> guessing that that assertion is when it's parsing the Python object
>>>>>>> returned by a re-implementation of a C++ virtual. That doesn't seem to
>>>>>>> be happening in the above which suggests things aren't happening where
>>>>>>> you think they are.
>>>>>>
>>>>>> sip module version is 4.19.19. You are correct, I oversimplified what
>>>>>> is actually happening. This is really what is happening:
>>>>>>
>>>>>> class LargeImageEditor(wxpg.PGEditor):
>>>>>> def CreateControls(self, propgrid, property, pos, sz):
>>>>>> ...
>>>>>> return wxpg.PGWindowList(self.tc, btn)
>>>>>>
>>>>>> Where CreateControls is a C++ virtual, relevant .sip snippet:
>>>>>>
>>>>>> virtual
>>>>>> wxPGWindowList CreateControls(
>>>>>> wxPropertyGrid * propgrid,
>>>>>> wxPGProperty * property,
>>>>>> const wxPoint & pos,
>>>>>> const wxSize & size
>>>>>> ) const = 0;
>>>>>> %Docstring
>>>>>> CreateControls(propgrid, property, pos, size) -> PGWindowList
>>>>>>
>>>>>> Instantiates editor controls.
>>>>>> %End
>>>>>
>>>>> So SIP need to copy the wxPGWindowList from the stack to the heap.
>>>>> Shouldn't CreateControls return a pointer to the wxPGWindowList?
>>>>>
>>>>> Of course SIP should detect this when generating the code rather than
>>>>> rely on a runtime assertion.
>>>>
>>>> That is probably how I would have designed the API, but alas it wasn't
>>>> done that way. :)
>>>>
>>>> Shouldn't a (default) copy constructor be sufficient to copy the
>>>> wxPGWindowList in this case?
>>>
>>> SIP may be being too conservative when determining if there is an implied
>>> copy ctor. Try adding an explicit copy ctor to the wxPGWindowList .sip
>>> file.
>>
>> I don't think that will be enough, though. SIP seems to only set the
>> assignment helper if there are *both* a public default constructor and
>> a public copy constructor, see:
>>
>> https://www.riverbankcomputing.com/hg/sip/file/d85e9957e726/sipgen/transform.c#l596
>>
>> Scott
>
> Should be fixed in the current repo. SIP v4.19.23 will be released next week.
>
> Be aware that the fix may expose missing private ctors in other .sip files -
> PyQt had two cases.
Thanks for the quick fix.
However, I think I found a situation with the new code where an assign
function is getting created where it probably shouldn't be.
struct wxSplitterRenderParams
{
%Docstring
SplitterRenderParams(widthSash_, border_, isSens_)
This is just a simple struct used as a return value of
wxRendererNative::GetSplitterParams().
%End
%TypeHeaderCode
#include <wx/renderer.h>
%End
wxSplitterRenderParams(
wxCoord widthSash_,
wxCoord border_,
bool isSens_
);
const wxCoord border;
const bool isHotSensitive;
const wxCoord widthSash;
}; // end of class wxSplitterRenderParams
This results in:
../../../../sip/cpp/sip_corewxSplitterRenderParams.cpp: In function ‘void
assign_wxSplitterRenderParams(void*, Py_ssize_t, void*)’:
../../../../sip/cpp/sip_corewxSplitterRenderParams.cpp:31:125: error: use
of deleted function ‘wxSplitterRenderParams&
wxSplitterRenderParams::operator=(const wxSplitterRenderParams&)’
31 | reinterpret_cast< ::wxSplitterRenderParams
*>(sipDst)[sipDstIdx] = *reinterpret_cast< ::wxSplitterRenderParams
*>(sipSrc);
|
^
In file included from
../../../../sip/cpp/sip_corewxSplitterRenderParams.cpp:12:
../../../../../Phoenix/ext/wxWidgets/include/wx/renderer.h:97:25: note:
‘wxSplitterRenderParams& wxSplitterRenderParams::operator=(const
wxSplitterRenderParams&)’ is implicitly deleted because the default
definition would be ill-formed:
97 | struct WXDLLIMPEXP_CORE wxSplitterRenderParams
| ^~~~~~~~~~~~~~~~~~~~~~
../../../../../Phoenix/ext/wxWidgets/include/wx/renderer.h:97:25: error:
non-static const member ‘const wxCoord wxSplitterRenderParams::widthSash’,
cannot use default assignment operator
../../../../../Phoenix/ext/wxWidgets/include/wx/renderer.h:97:25: error:
non-static const member ‘const wxCoord wxSplitterRenderParams::border’,
cannot use default assignment operator
../../../../../Phoenix/ext/wxWidgets/include/wx/renderer.h:97:25: error:
non-static const member ‘const bool
wxSplitterRenderParams::isHotSensitive’, cannot use default assignment
operator
Scott
More information about the PyQt
mailing list