Python + Windows + distutils + SWIG + gcc MinGW

or "Creating Python extensions in C/C++ with SWIG and compiling them with MinGW gcc under Windows"
or "Installing Python extension with distutils and without Microsoft Visual C++".

This page is located at http://sebsauvage.net/python/mingw.html.
This page was written by Sébastien SAUVAGE <sebsauvage at sebsauvage dot net>.
Last update : July 26th, 2003.

This page is a cookbook for creating Python extensions in C/C++ under Windows with SWIG, distutils and gcc (MinGW version).
It may also prove to be more generally helpful in installing/compiling existing C/C++ Python extension without Microsoft Visual C++ compiler.

Note: This documentation is outdated and may not be relevant against the most recent versions of Python, SWIG and MinGW (See notes at the end of the document).


What's the point ?

Under Windows, if you do not have the costly Microsoft Visual C++, you cannot install Python extensions written in C. Dot. (ever wondered why they did choose the commercial MSVC++ and not the opensource GCC ? I just can't grasp the reason... whatever.).

This page will help to achieve exaclty this (and more: create your own extensions) with the opensource compiler gcc. The MinGW variant of gcc does not require POSIX-emulation external DLL (like CygWin).

SWIG and distutils are not compulsory for creating C/C++ Python extensions under Windows, but SWIG will take care of the gory details of wrapping your C/C++ code, and disutils will compile and link the code for you (and it will also help in installing your extensions on other systems).

The steps are:

  1. Get and install MinGW gcc
  2. Create libpython22.a
  3. Tweak distutils
  4. Get and install SWIG
  5. Create an extension
  6. Compile/install the extension with distutils
  7. Use the new extension

If you do not intend to create your own extension (but simply install an existing one), you can skip steps 4 and 5.


1. Get and install MinGW gcc

Download the compiler from http://www.mingw.org. This GCC compiler runs under Windows and compiled programs do not require support DLL like CygWin GCC.

You only need to download MinGW-1.1.tar.gz (roughly 10,6 Mb). It contains the whole compiler, support utilities, documentation, librairies and header files.

Once decompressed, you should add the \bin directory of MinGW to your path environment variable.
(Example : Under Windows 95/98/ME, if you installed MinGW to c:\gcc, you would add SET PATH=c:\gcc\bin;%PATH% to your AUTOEXEC.BAT.)

If installed properly, you should be able to run gcc --version anywhere. (Mine displays : 2.95.3-6).

 

2. Create libpython22.a

To create Python extensions, you need to link against the Python library. Unfortunately, most Python distributions are provided with Python22.lib, a library in Microsoft Visual C++ format. GCC expects a .a file (libpython22.a to be precise.). Here's how to convert python22.lib to libpython22.a:

  1. Download pexport (from here or http://starship.python.net/crew/kernr/mingw32/pexports-0.42h.zip).
  2. Get Python22.dll (it should be somewhere on your harddrive).
  3. Run : pexports python22.dll > python22.def
    This will extract all symbols from python22.dll and write them into python22.def.
  4. Run : dlltool --dllname python22.dll --def python22.def --output-lib libpython22.a
    This will create libpython22.a (dlltool is part of MinGW utilities).
  5. Copy libpython22.a to c:\python22\libs\ (in the same directory as python22.lib).

This trick should work for all Python versions, including future releases of Python. You can also use this trick to convert other libraries.


3. Tweak distutils

This tweak is necessary with Python 2.2, but by the time I write this distutils may have been corrected.

You can compile and link your Python extensions yourself, but distutil is the preffered way (it will make all the necessary calls to the different compilers, call SWIG if necessary and your extensions will be easier to distribute).

Locate build_ext.py in your Python directory (should be somewhere around C:\Python22\Lib\distutils\command\).

Change the 2 following lines:

#new_sources.append(base + target_ext) # old
new_sources.append(base + '_wrap' + target_ext) # new

#swig_cmd = [swig, "-python", "-dnone", "-ISWIG"] # old
swig_cmd = [swig, "-python"] # new


4. Get and install SWIG

SWIG is a wrapper for C/C++ sources. It allows you to use C/C++ functions and classes from withing Python with a minimum effort.

Download SWIG binaries for Window from http://www.swig.org, decompress them and add swig directory to your path (the directory where swig.exe is located).


5. Create an extension

The following example is taken from SWIG website. Create the following files:

example.c - our Python extension written in C

/* File : example.c */

#include <time.h>
double My_variable = 3.0;

int fact(int n)
{
    if (n <= 1) return 1;
    else return n*fact(n-1);
}

int my_mod(int x, int y)
{
    return (x%y);
}

char *get_time()
{
    time_t ltime;
    time(&ltime);
    return ctime(&ltime);
}

example.i [required for SWIG] - interface declaration of our extension.

/* example.i */
%module example
%{
/* Put header files here (optional) */
%}

extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();

The .i file contains the interface. You can simply include your .h files if you have any (put #include "myheaders.h" within %{ ... }% ).


6. Compile/install the extension with distutils

Create the following file:

setup.py [required for disutils] - setup script for distutils

# setup.py
import distutils
from distutils.core import setup, Extension

setup(name = "Simple example from the SWIG website",
      version = "2.2",
      ext_modules = [Extension("example", ["example.i","example.c"])])

Then run:

python setup.py build -cmingw32

This will automatically:

(See distutils manual for more information on distutil scripts).

You may get a few warning about "declared but unused" symbols. You can safely ignore them.

Look into the \build\lib.win32-2.2 subdirectory: you should see example.pyd. This is our compiled module. Now you can use it.

 

7. Use the new extension

Put example.pyd in your PYTHONPATH, or in current directory.

Usage example

>>> import example
>>> example.fact(5)
120
>>> example.my_mod(7,3)
1
>>> example.get_time()
'Wed Aug 07 20:02:06 2002\n'
>>>

The generated .pyd file will run under Windows 95/98/ME/NT/2000/XP. This is a DLL which depends only on msvcrt.dll (Microsoft VisualStudio C++ Runtime) and Python22.dll.

If you itend to distribute the .pyd file, keep in mind that you will have to create a .pyd file for each Python DLL version.

SWIG automatically wraps C data types to Python data types. When SWIG cannot guess how to do the mapping, you will have to add C/C++ functions in the .i file. (See SWIG documentation for more information about mappings).


2003-07-26: I've been told that that SWIG 1.3.19 requires the following change in setup.py:

change: ext_modules = [Extension("example", ["example.i","example.c"])])
to: ext_modules = [Extension("_example", ["example.i","example.c"])])

Big thank to Bob Reynolds ( ''.join([chr(ord(c)-2) for c in 'DqdaTg{pqnfuBeqoecuv0pgv']) ) for providing this information.

2004-04-29: According to Mike, the disutil tweak is no longer necessary. Creating the .a file is also no longer necessary: Just copy the Python DLL to the \libs directory.

Thanks to Mike for this information (  ''.join([chr(ord(c)-2) for c in 'okmgBokmgnkp0ec']) ).


References: