Peter's Blog

Redefining the Impossible

Swig Howto


A quick reminder on how to use Swig under Windows XP to generate Python modules with Visual Studio 6.

  • Download Windows version of Swig
  • Unzip it somewhere, I put it in c:/Python24/Swig
  • Create the following environment variables:
    PYTHONINCLUDE = c:\python24\include
    PYTHONLIB = c:\Python24\Libs
    
  • Create a project in Visual Studio for a plain empty win32 dll.
  • In all build settings, make sure the following settings are added:
    Additional include directories = c:\python24\include
    Additional library path = c:\python24\libs
    
  • Create swig definition file. Here is mine, it's for a CAN bus control module:
       1  %module pyCan
       2  %include exception.i
       3  %{
       4  #include <windows.h>
       5  #include <stdlib.h>
       6  #include <stdio.h>
       7  #include <string.h>
       8  #include "pyCan.h"
       9  %}
      10  
      11  /*
      12   * When a c++ exception occurs, this code will turn it into
      13   * a python exception. Cool.
      14   */
      15  %exception {
      16      try {
      17          $action
      18      } catch( char *strError) {
      19          PyErr_SetString(PyExc_RuntimeError, strError);
      20          return NULL;
      21      }
      22  }
      23  
      24  /*
      25   * The function GetRxPacket returns a new object that python
      26   * memory management must delete when required.
      27   */
      28  %newobject GetRxPacket;
      29  
      30  /*
      31   * Class that will become a python class. The python class will have
      32   * the same methods available.
      33   */
      34  class pyCan {
      35  public:
      36      pyCan( void);
      37      ~pyCan( void);
      38      void Initialise( void);
      39      void Poll( void);
      40      pyCanPacket *GetRxPacket( void);
      41      void TxPacket( int nID, PyObject *);
      42  };
    
  • Add the Swig file to the project, right click and select 'settings'. Set the custom build commands something like the following:
    c:\python24\swig\swig -c++ -module pyCan -python c:\projects\694\src\pyCan\pyCan\pyCan.swig
    
    Where
    
        -c++ = generate c++
        -module pyCan = output module is called 'pyCan
        -python = generate python module
        c:\projects\694\src\pyCan\pyCan\pyCan.swig = swig file name
    
  • The above will generate a c++ file called 'pyCan_wrap.cxx'. This should be put into the 'Outputs' box in the custom build step.
  • Run the build on the swig file to create the wrapper file pyCan_wrap.cxx and add that file to the project.
  • Set the link target to something like
    _pyCan.dll
    
    I.e. the name of the module with an underscore in front.
  • Create a 'real' c++ header and implementation for your classes. They can be totally straight c++, e.g.:
    class pyCan {
    public:
        pyCan( void);
        ~pyCan( void);
        void Initialise( void);
        void Poll( void);
        pyCanPacket *GetRxPacket( void);
        void TxPacket( int nID, PyObject *);
    };
    
    In the above example I am passing a PyObject * to the function TxPacket. This is because I want to be able to pass python strings that may contain null characters and I want access to both the pointer to the data and the data length, which the raw PyObject gives me. If I only wanted a char * I would simply put that in the argument.
  • Build it
  • Swig will create a file called 'pyCan.py' which is the python wrapper module that loads the dll. It is the file that your python must import. You might want to add a post-build step to copy this somewhere more useful. You may also put the link target file in the same directory or you will get errors when you import the module.
  • Write some python:
    import pyCan
    
    o = pyCan.pyCan()
    o.Initialise()
    while 1:
        o.Poll()
        r = o.GetRxPacket()
        if r:
            print r
    

Swig is quite easy to get going. I think it has real power but there is a lot of documentation to go through to fully understand what it can do and the documentation and semantics are not all that clear. The PyObject trick above was a guess of mine that happened to work.


Filed under: python swig windows

Anonymous Says:

over 3 years ago

All those debates. Dean.

Peter Says:

over 3 years ago

It took me about 2 days to get CAN going, including getting firmware talking and a python extension listening. So much easier than USB/RS232.

Peter

Comments are Closed