Compile Cython Module on Windows

In this post, I am showing how to compile Cython modules on Windows, which often leads to weird error messages.

(Cython references: http://cython.org/, http://docs.cython.org/index.html, https://github.com/cython/cython)

1. You should already have correct structure to hold your “.pyx” file. Also, `setup.py` needs to be correctly configured. The following shows an example of `setup.py`:

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

from Cython.Build import cythonize
import numpy

config = {
    'description': 'SimpleCNN',
    'author': 'Zhengxing Chen',
    'author_email': 'czxttkl@gmail.com',
    'install_requires': ['nose','numpy','scipy','cython'],
    'packages': ['simplecnn'], 
    'name':"SimpleCNN",
    'ext_modules':cythonize("simplecnn/pool.pyx"),       # change path and name accordingly 
    'include_dirs':[numpy.get_include()]                 # my cython module requires numpy
}

setup(**config)

2. Based on the instruction on the official guide of Cython (http://docs.cython.org/src/quickstart/build.html#building-a-cython-module-using-distutils), I tried:

python setup.py build_ext --inplace

But it turned out that Visual Studio 2008 was not found in my path. And I was suggested to use mingw64 to compile the code. Luckily, I have installed mingw64 on my Windows machine.

Unnamed QQ Screenshot20150511075341

However, another error jumped in when I used:

python setup.py build_ext --inplace -c mingw64

2The error went like:

gcc: error: shared and mdll are not compatible
error: comand 'dllwrap' failed with exit status 1

I don’t know the meaning of “shared and mdll are not compatible”. But after some experiments, I found that giving gcc the parameter “-mdll” rather than “-shared” will bypass such error and manage to build your Cython module. In light of this, we need to modify the code in `cygwinccompiler.py` file in `distutils` package. You can locate `cygwinccompiler.py` file using search on Windows:

5

In the file, it has a _compile function which is needed to change (see the red part below):

    def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
        if ext == '.rc' or ext == '.res':
            # gcc needs '.res' and '.rc' compiled to object files !!!
            try:
                self.spawn(["windres", "-i", src, "-o", obj])
            except DistutilsExecError, msg:
                raise CompileError, msg
        else: # for other files use the C-compiler
            try:
                print "i changed the code in Lib/distutils/cygwinccompiler.py line 163"
                self.compiler_so[2] = '-mdll'
                self.linker_so[1] = '-mdll'
                print self.compiler_so
                print self.linker_so
                self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +
                           extra_postargs)
            except DistutilsExecError, msg:
                raise CompileError, msg

After that, remember to invalidate (remove) `cygwinccompiler.pyc` file so that you make sure Python will recompile `cygwinccompiler.py` and your modification will take effect.

FinallyI re-tried to compile Cython code and it worked since then. A `.pyd` file was generated on the same folder as the `.pyx` file.

4

Leave a comment

Your email address will not be published. Required fields are marked *