swig with wxPython

getting swig + wxPython working well...

Hi, I'm trying to extend wxPython with C++, and when I run swig on my .i file,
it tells me it doesn't know what a wxWindow is, and it's ignoring it.

How can I get my C++ extensions working well? Can I use the latest swig instead?

I'm using Robin's wxPython-2.6.1.0 libs+includes, and a 1.3.24 version of swig +
Robin's patches.

I might not have the patches applied correctly, but looking at what the patches
fix (making copies of objects that don't have a copy constructor, etc.) it
doesn't look like it would make any difference.

···

-----------------------------------------------
Here's my .i:

%{
#include "wx/wxPython/wxPython.h"
#include "imaging/big/tileCache.h"
#include "tracing/neuroinfo/VisibleArea.h"
#include "imaging/wx/imageNavigator.h"
#include "imaging/wx/slideWindowOverlay.h"
%}

%import typemaps.i
%import my_typemaps.i

%pragma(python) code = "import wx"

class SlideWindow: public wxWindow, public ImageNavigatorListener
{
public:
    SlideWindow(wxWindow *parent);
...

-----------------------------------------------
and Here's how I'm invoking swig from visual studio:

c:\jimc\prj\bright\tools\swig -c++ -python
-IC:\jimc\prj\bright\libs\wxPython-2.6.1.0\include\wx\wxPython\i_files -o
$(ProjectDir)\gen\$(InputName)_wrap.cpp "$(InputPath)"

-----------------------------------------------
And here's my output:

c:\jimc\prj\bright\src\imaging\wx\slideWindow.i(26): Warning(401): Nothing known
about base class 'wxWindow'. Ignored.
c:\jimc\prj\bright\src\imaging\wx\macroWindow.i(25): Warning(401): Nothing known
about base class 'wxWindow'. Ignored.

Thanks!
-Jim

try here:
%import windows.i

and maybe a %import core.i is needed too.

···

On Fri, 2005-12-16 at 21:09 +0000, Jim Carroll wrote:

> getting swig + wxPython working well...

Hi, I'm trying to extend wxPython with C++, and when I run swig on my .i file,
it tells me it doesn't know what a wxWindow is, and it's ignoring it.

How can I get my C++ extensions working well? Can I use the latest swig instead?

I'm using Robin's wxPython-2.6.1.0 libs+includes, and a 1.3.24 version of swig +
Robin's patches.

I might not have the patches applied correctly, but looking at what the patches
fix (making copies of objects that don't have a copy constructor, etc.) it
doesn't look like it would make any difference.

-----------------------------------------------
Here's my .i:

%{
#include "wx/wxPython/wxPython.h"
#include "imaging/big/tileCache.h"
#include "tracing/neuroinfo/VisibleArea.h"
#include "imaging/wx/imageNavigator.h"
#include "imaging/wx/slideWindowOverlay.h"
%}

%import typemaps.i
%import my_typemaps.i

--

"Unix is very user-friendly. It's just picky about who its friends are."
http://rpedroso.freesuperhost.com/

Jim Carroll wrote:

getting swig + wxPython working well...

Hi, I'm trying to extend wxPython with C++, and when I run swig on my .i file,
it tells me it doesn't know what a wxWindow is, and it's ignoring it.

How can I get my C++ extensions working well? Can I use the latest swig instead?

I'm using Robin's wxPython-2.6.1.0 libs+includes, and a 1.3.24 version of swig +
Robin's patches.

I might not have the patches applied correctly, but looking at what the patches
fix (making copies of objects that don't have a copy constructor, etc.) it
doesn't look like it would make any difference.

-----------------------------------------------
Here's my .i:

%{
#include "wx/wxPython/wxPython.h"
#include "imaging/big/tileCache.h"
#include "tracing/neuroinfo/VisibleArea.h"
#include "imaging/wx/imageNavigator.h"
#include "imaging/wx/slideWindowOverlay.h"
%}

%import typemaps.i
%import my_typemaps.i

%pragma(python) code = "import wx"

class SlideWindow: public wxWindow, public ImageNavigatorListener
{
public:
    SlideWindow(wxWindow *parent);
...

Starting with wxPython 2.5.x the method for how to use SWIG for wxPython aware extesions has changed a bit, (because of the switch from SWIG 1.1 to 1.3.) For examples you can take a look at the wxMozilla code, or even in the wxPython modules under wxPython/contrib in the source tree. At a minimum you need to tell SWIG to import the core.i module for it to find all the definitions of the core classes and macros. I do it like this:

%import core.i
%pythoncode { import wx }
%pythoncode { __docfilter__ = wx._core.__DocFilter(globals()) }

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

  At a minimum you need to tell SWIG to import the core.i module for it
to find all the definitions of the core classes and macros. I do it
like this:

%import core.i
%pythoncode { import wx }
%pythoncode { __docfilter__ = wx._core.__DocFilter(globals()) }

This gets me pretty far... Now the generated swig .cc file is compiling
until it gets about 8000 lines into it, then it has trouble finding
wxPySizer

(now compiling under Linux...)

g++ -DGTK_NO_CHECK_CASTS -D__WXGTK__ -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES
-D_LARGEFILE_SOURCE=1 -pthread -fPIC -I/home/jimc/prj/bright/src
-I/home/jimc/prj/bright/libs/crypto521 -I/usr/include/python2.4
-I/usr/include/wx-2.6/wx/wxPython/i_files
-I/usr/lib/wx/include/gtk2-ansi-release-2.6 -I/usr/include/wx-2.6 -c -o
/home/jimc/prj/bright/src/bright_wrap.os /home/jimc/prj/bright/src/bright_wrap.cc
/home/jimc/prj/bright/src/bright_wrap.cc: In function 'void*
_p_wxPySizerTo_p_wxObject(void*)':
/home/jimc/prj/bright/src/bright_wrap.cc:8773: error: 'wxPySizer' was not
declared in this scope
/home/jimc/prj/bright/src/bright_wrap.cc:8773: error: expected
primary-expression before 'void'
/home/jimc/prj/bright/src/bright_wrap.cc:8773: error: expected `)' before
'void'/home/jimc/prj/bright/src/bright_wrap.cc: In function 'void*
_p_wxPyValidatorTo_p_wxObject(void*)':
/home/jimc/prj/bright/src/bright_wrap.cc:8926: error: 'wxPyValidator' was not
declared in this scope

I've found wxPySizer is renamed in __core_rename.i, which is included from
core.i, so I'm suprised SWIG isn't finding it.

Thanks for any help,
-Jim

Jim Carroll wrote:

At a minimum you need to tell SWIG to import the core.i module for it to find all the definitions of the core classes and macros. I do it like this:

%import core.i
%pythoncode { import wx }
%pythoncode { __docfilter__ = wx._core.__DocFilter(globals()) }

This gets me pretty far... Now the generated swig .cc file is compiling
until it gets about 8000 lines into it, then it has trouble finding
wxPySizer

(now compiling under Linux...)

g++ -DGTK_NO_CHECK_CASTS -D__WXGTK__ -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES
-D_LARGEFILE_SOURCE=1 -pthread -fPIC -I/home/jimc/prj/bright/src
-I/home/jimc/prj/bright/libs/crypto521 -I/usr/include/python2.4
-I/usr/include/wx-2.6/wx/wxPython/i_files
-I/usr/lib/wx/include/gtk2-ansi-release-2.6 -I/usr/include/wx-2.6 -c -o
/home/jimc/prj/bright/src/bright_wrap.os /home/jimc/prj/bright/src/bright_wrap.cc
/home/jimc/prj/bright/src/bright_wrap.cc: In function 'void*
_p_wxPySizerTo_p_wxObject(void*)':
/home/jimc/prj/bright/src/bright_wrap.cc:8773: error: 'wxPySizer' was not
declared in this scope
/home/jimc/prj/bright/src/bright_wrap.cc:8773: error: expected
primary-expression before 'void'
/home/jimc/prj/bright/src/bright_wrap.cc:8773: error: expected `)' before
'void'/home/jimc/prj/bright/src/bright_wrap.cc: In function 'void*
_p_wxPyValidatorTo_p_wxObject(void*)':
/home/jimc/prj/bright/src/bright_wrap.cc:8926: error: 'wxPyValidator' was not
declared in this scope

I've found wxPySizer is renamed in __core_rename.i, which is included from
core.i, so I'm suprised SWIG isn't finding it.

SWIG is finding it, you've already gotten past the SWIG part. Now you need to tell the C++ compiiler where to find the C++ class definitions by adding more #include directives. Both of these are in wx/wxPython/pyclasses.h.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

SWIG is finding it, you've already gotten past the SWIG part. Now you
need to tell the C++ compiiler where to find the C++ class definitions
by adding more #include directives. Both of these are in
wx/wxPython/pyclasses.h.

Fantastic! It's compiling now. Thanks Robin!

I'm tempted to try to keep some notes when things go well, where's a good
public place for this sort of thing? Maybe the wxPython wiki?

-Jim

> SWIG is finding it, you've already gotten past the SWIG part. Now you
> need to tell the C++ compiiler where to find the C++ class definitions
> by adding more #include directives. Both of these are in
> wx/wxPython/pyclasses.h.

Fantastic! It's compiling now. Thanks Robin!

Oops, I got ahead of myself. It's compiling, but when I try to use it I get:

Python 2.4.1 (#65, Mar 30 2005, 09:13:57) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

import bright

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "bright.py", line 573, in ?
    class SlideWindow(wx._core.Window,ImageNavigatorListener):
  File "bright.py", line 576, in SlideWindow
    for _s in [wx._core.Window,ImageNavigatorListener]: __swig_setmethods__.upda
te(_s.__swig_setmethods__)
AttributeError: type object 'Window' has no attribute '__swig_setmethods__'

The code is:

class SlideWindow(wx._core.Window,ImageNavigatorListener):
    """Proxy of C++ SlideWindow class"""
    __swig_setmethods__ = {}
    for _s in [wx._core.Window,ImageNavigatorListener]:
__swig_setmethods__.update(_s.__swig_setmethods__)
    __setattr__ = lambda self, name, value: _swig_setattr(self, SlideWindow,
name, value)
    __swig_getmethods__ = {}

I guess wx.Window doesn't have __swig_setmethods__

Hmm.... Anyone know what I could be doing wrong? Can I dynamically add the
dictionary with that name into wx._core.Window safely?

Thanks,
-Jim Carroll

Jim Carroll wrote:

SWIG is finding it, you've already gotten past the SWIG part. Now you need to tell the C++ compiiler where to find the C++ class definitions by adding more #include directives. Both of these are in wx/wxPython/pyclasses.h.

Fantastic! It's compiling now. Thanks Robin!

Oops, I got ahead of myself. It's compiling, but when I try to use it I get:

Python 2.4.1 (#65, Mar 30 2005, 09:13:57) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

import bright

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "bright.py", line 573, in ?
    class SlideWindow(wx._core.Window,ImageNavigatorListener):
  File "bright.py", line 576, in SlideWindow
    for _s in [wx._core.Window,ImageNavigatorListener]: __swig_setmethods__.upda
te(_s.__swig_setmethods__)
AttributeError: type object 'Window' has no attribute '__swig_setmethods__'

The code is:

class SlideWindow(wx._core.Window,ImageNavigatorListener):
    """Proxy of C++ SlideWindow class"""
    __swig_setmethods__ = {}
    for _s in [wx._core.Window,ImageNavigatorListener]:
__swig_setmethods__.update(_s.__swig_setmethods__)
    __setattr__ = lambda self, name, value: _swig_setattr(self, SlideWindow,
name, value)
    __swig_getmethods__ = {}

I guess wx.Window doesn't have __swig_setmethods__

Do you use the same version of SWIG that I do? (1.3.24 plus some patches located here: http://cvs.wxwidgets.org/viewcvs.cgi/wxWidgets/wxPython/SWIG/)

Do you use the same SWIG command-line parameters that I do? (Something like this: "-c++ -Wall -nodefault -python -keyword -new_repr -modern -D__WXGTK__") If you use wxPython's config.py to run SWIG for you then this should be automatic.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Jim Carroll wrote:

I'm tempted to try to keep some notes when things go well, where's a good
public place for this sort of thing? Maybe the wxPython wiki?

Please do. There is a page there already on writing C++ extenstions with SWIG for wxPython compatibility, but it is really out of date. Updating that page would be a very nice thing.

http://wiki.wxpython.org/index.cgi/C_2b_2bExtensions

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Jim Carroll wrote:

I'm tempted to try to keep some notes when things go well, where's a good
public place for this sort of thing? Maybe the wxPython wiki?

Absolutely. A wiki page about writing your own C++ extensions to wxPython would be great!

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Thanks for all the help Robin,

Do you use the same version of SWIG that I do? (1.3.24 plus some
patches located here:
http://cvs.wxwidgets.org/viewcvs.cgi/wxWidgets/wxPython/SWIG/)

Do you use the same SWIG command-line parameters that I do? (Something
like this: "-c++ -Wall -nodefault -python -keyword -new_repr -modern
-D__WXGTK__") If you use wxPython's config.py to run SWIG for you then
this should be automatic.

I updated my swig invocation, and It's almost working!

I can import my module, insntantiate my classes, and it all looks
like it's working great... until I try to pass my wxWindow-derived
class to sizer.Add()

------------My Code that uses the new wrapped SlideWindow class:
(from within a wxFrame __init__)
        self.slideWindow = bright.SlideWindow(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
-> sizer.Add(self.slideWindow, 1, wx.EXPAND)
        self.SetSizer(sizer)

------------Gives me the error:
Traceback (most recent call last):
  File "C:\jimc\prj\bright\scripts\densitometry\view_frame.py",
    line 70, in ? dlg = ViewFrame()
  File "C:\jimc\prj\bright\scripts\densitometry\view_frame.py",
    line 29, in __init__
    sizer.Add(self.slideWindow, 1, wx.EXPAND)
  File "C:\Python24\lib\site-packages\wx-2.6-msw-ansi\
    wx\_core.py", line 11476,
in Add
    return _core_.Sizer_Add(*args, **kwargs)
TypeError: wxWindow, wxSizer, wxSize, or (w,h) expected for item

···

------------

Which tells me that the following check in __core_wrap.cpp
(line 2972) is failing:

    if ( ! wxPyConvertSwigPtr(item, (void**)&info.window,
           wxT("wxWindow")) ) {

My generated code for my SlideWindow does seem to have all the
inheritance working:
-------------
class SlideWindow(wx._core.Window,ImageNavigatorListener):
    """Proxy of C++ SlideWindow class"""

-------------
My .i file looks like this:
(#includes...)

%import windows.i
%import core.i
%pythoncode { import wx }
%pythoncode { __docfilter__ = wx._core.__DocFilter(globals()) }

class SlideWindow: public wxWindow, public ImageNavigatorListener
{
public:
    SlideWindow(wxWindow *parent);
    %pythonAppend SlideWindow "self._setOORInfo(self)"

    void SetImageNavigator(ImageNavigator *pin);

    void OnMouse(wxMouseEvent& event);
    virtual void OnPaint(wxPaintEvent &WXUNUSED(event));
    void OnSize(wxSizeEvent& event);

    void AddOverlay(SlideWindowOverlay *pOverlay);

protected:
    virtual void ViewChanged();

};

-------------

What else do I need to make sure that my class is recognized by wxPython as a
wxWindow?

Thanks!
-Jim

Jim Carroll wrote:

Thanks for all the help Robin,

Do you use the same version of SWIG that I do? (1.3.24 plus some patches located here: http://cvs.wxwidgets.org/viewcvs.cgi/wxWidgets/wxPython/SWIG/)

Do you use the same SWIG command-line parameters that I do? (Something like this: "-c++ -Wall -nodefault -python -keyword -new_repr -modern -D__WXGTK__") If you use wxPython's config.py to run SWIG for you then this should be automatic.

I updated my swig invocation, and It's almost working!

I can import my module, insntantiate my classes, and it all looks like it's working great... until I try to pass my wxWindow-derived class to sizer.Add()

------------My Code that uses the new wrapped SlideWindow class:
(from within a wxFrame __init__)
        self.slideWindow = bright.SlideWindow(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
-> sizer.Add(self.slideWindow, 1, wx.EXPAND)
        self.SetSizer(sizer)

------------Gives me the error:
Traceback (most recent call last):
  File "C:\jimc\prj\bright\scripts\densitometry\view_frame.py", line 70, in ? dlg = ViewFrame()
  File "C:\jimc\prj\bright\scripts\densitometry\view_frame.py", line 29, in __init__
    sizer.Add(self.slideWindow, 1, wx.EXPAND)
  File "C:\Python24\lib\site-packages\wx-2.6-msw-ansi\
    wx\_core.py", line 11476,
in Add
    return _core_.Sizer_Add(*args, **kwargs)
TypeError: wxWindow, wxSizer, wxSize, or (w,h) expected for item
------------

Which tells me that the following check in __core_wrap.cpp (line 2972) is failing:

    if ( ! wxPyConvertSwigPtr(item, (void**)&info.window, wxT("wxWindow")) ) {

You probably need to add the following define to your CFLAGS when compiling the wrapper code. It specifies the name to use for the typeinfo table where swig stores all the infomation about the class heirarchy that it is wrapping.

  -DSWIG_TYPE_TABLE=_wxPython_table

To double check try this:

  >>> import wx
  >>> import YourModule
  >>> import swig_runtime_data1
  >>> dir(swig_runtime_data1)
  ['__doc__', '__name__', 'type_pointer_wxPython_table']
  >>>

If you have more than one table inthe swig_runtime_data1 module then the problem is that wxPython's functions are not seeing the typeinfo for your class and you need to add the definition for SWIG_TYPE_TABLE.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

To double check try this:

  >>> import wx
  >>> import YourModule
  >>> import swig_runtime_data1
  >>> dir(swig_runtime_data1)
  ['__doc__', '__name__', 'type_pointer_wxPython_table']
  >>>

Sure enough, I had an older define:
  SWIG_TYPE_TABLE=wxPython_type_table

based on some old example. checking the swig_runtime_data1 showed
that there were two different tables, and when I changed my define
everything started working. I now have:
  SWIG_TYPE_TABLE=_wxPython_table

This also fixed an older problem where I could interactively work
with wxImage* but not wxImage objects returned from C++

Thanks Robin!
You da man.