Grid GetDefaultRenderer returns a pointer

The documentation for Grid GetDefaultRenderer (wx.grid.Grid — wxPython Phoenix 4.1.2a1 documentation) indicates that this method Returns a pointer to the current default grid cell renderer.

In python this means that if we call SetDefaultRenderer with a custom renderer, a subsequent call to GetDefaultRenderer does not return our python object but some <wx._grid.GridCellRenderer object at 0x7f57361c5948>.

An attempt to cast this object to its actual python object like:

myRenderer = myGrid.GetDefaultRenderer()
myRenderer.__class__ = MyRenderer.__class__

fails with TypeError: __class__ assignment only supported for heap types or ModuleType subclasses

This means that GetDefaultRenderer is not very useful in python. Evidently one can keep track of the python object without relying on GetDefaultRenderer, but I feel this is a particular instance of a more general problem with these methods that return pointers. And I wonder if there is something that we could do in sip for these methods.

Most of the time returning pointers works as expected. For example, wxWindow::GetTopLevelParent returns a wxWindow pointer, but from Python it will give you the original Python instance of the parent frame, if it was created from Python in the first place.

But for some cases, like the grid cell attributes, renderers and editors, there are copies made internally in the grid C++ code when merging attributes for row, col and cell, and so when you call something like GetDefaultRenderer what is returned is a pointer with a different value than the pointer for the original object. For example, here is the output of printing self in the __init__ for a custom renderer class, followed by a print of what was returned from GetDefaultRendererForCell:

<GridStdEdRend.MyCustomRenderer object at 0x7f8a186a9dc0>
<wx._grid.GridCellRenderer object at 0x7f8a186fbe50>

Notice the different addresses. So since SIP doesn’t see that pointer in its cache the only thing it can do is create a new proxy object with the same base type as the pointer.

SIP does have the ability to cast objects, although you need to take care that it really is of the specified type. For example:

import wx.siplib
r = grid.GetDefaultRenderer()
r = wx.siplib.cast(r, MyRendererClass)
1 Like