Passing Python wxGLCanvas to C++

I typed this message up once only to have Google eat it. Sorry if Google
later decides to post the original.

It wasn't eaten, it was held for moderation since it is the first time you've posted to this group and we want to make sure you are not a spam-spewing robot.

I've got several OpenGL renderers written in C++ around which I am
trying to tack a wxPython-powered GUI. For the most part, the OpenGL/C++
layer knows nothing about the windowing layer, which is good. However,
occasionally code in the OpenGL/C++ layer needs to force a refresh of
the wxGLCanvas. (I'm not doing continuous rendering.) It's not clear to
me how I can trigger this refresh.

My first thought was to expose a way to register a wxGLCanvas on the C++
side of things. I've attached a minimal example. The method
TriggerRefresh in Renderer.{h,cpp} receives a pointer to a wxGLCanvas
and does something with it. I fed Swig the attached tobind.i to create
Python bindings for the Renderer class. All these produced a Python
module I named render. Finally, in renderer_test.py, I create a wx.App,
a Renderer, and wxGLCanvas. However, when I try to register the Python
wxGLCanvas with the TriggerRefresh binding, I get a TypeError:

    Traceback (most recent call last):
    File "renderer_test.py", line 9, in <module>
    renderer.TriggerRefresh(canvas)
    File
    "/home/cjohnson/checkouts/cj_graphics/trunk/wxpython/render.py",
    line 75, in TriggerRefresh
    def TriggerRefresh(self, *args): return
    _render.Renderer_TriggerRefresh(self, *args)
    TypeError: in method 'Renderer_TriggerRefresh', argument 2 of type
    'wxGLCanvas *'

Swig and I haven't been buds for long. I'm very grateful for any help
you can give me.

You need to ensure that you are using the same swig that wxPython is using (including patches) and you need to build your extension module with the same compile flags that wxPython is using. The first will ensure that the runtime type info is compatible, and the second will ensure that the type information is shared between the extension modules.

There are notes about the swig version, patches and where to get a pre-patched tarball in the wxPython source tarball at wxPython/SWIG.

One way to ensure that you are using the same compile flags is to have your setup.py import and use the wx.build.config module. You'll find a ton of stuff in there including helper functions and lists of flags and such.

import wx
from wxPython.glcanvas import wxGLCanvas
import render

app = wx.App()
frame = wx.Frame(None, title='A Test')
canvas = wxGLCanvas(frame, wx.ID_ANY)
renderer = render.Renderer()
renderer.TriggerRefresh(canvas)

BTW, don't do your import like the 2nd line above, the wxPython package is almost totally dead and gone. Instead you should do something like "from wx.glcanvas import GLCanvas"

···

On 6/13/12 6:00 PM, Chris Johnson wrote:

--
Robin Dunn
Software Craftsman

I typed this message up once only to have Google eat it. Sorry if Google

later decides to post the original.

It wasn’t eaten, it was held for moderation since it is the first time
you’ve posted to this group and we want to make sure you are not a
spam-spewing robot.

I noticed that after I submitted the third time.

You need to ensure that you are using the same swig that wxPython is
using (including patches) and you need to build your extension module
with the same compile flags that wxPython is using.

[…]

One way to ensure that you are using the same compile flags is to have
your setup.py import and use the wx.build.config module. You’ll find a
ton of stuff in there including helper functions and lists of flags and
such.

I’m thankful for your direction on this, but I must confess that aligning SWIG and wxPython doesn’t sound like a lot of fun to me. I use CMake to generate my bindings, rather than distutils, and the process just keeps getting more roundabout.

Thinking a bit more about the problem, I discovered that I can produce an intermediary hierarchy for managing the boundary. A superclass with virtual methods resides on the C++ side and has a more or less abstract Refresh() method. A subclass on the Python side overrides Refresh() and updates the canvas as needed. I had to enable directors in my SWIG file, but I think it’s working okay. Since the hierarchy is entirely owned by me and I produced its bindings, I can use whatever SWIG I have laying around.

Thanks again.

  • Chris
···

On Wednesday, June 13, 2012 8:44:23 PM UTC-5, Robin Dunn wrote:

On 6/13/12 6:00 PM, Chris Johnson wrote: