cabraut
cabraut

Reputation: 33

Problems with SWIG, mingw32, distutils

I have been trying to set up a Python 2.7 environment under Windows 7 so that I can compile a C++ extension for use in Python. Since I am new to this, I have downloaded a simple example here and have used the files verbatim. I also have a numpy.i file in the path. I have set up my computer with mingw (latest version) and swig (v. 3.0.10), and my Python version is 2.7.9. I have even used this environment to compile a small C++ program using g++ with no problem.

But when trying to build the "simple" Python extension referenced above, I always get the following output, indicating failure (I have included the command that I issued in the Windows cmd.exe window as the first line below):

python setup.py build -c=mingw32
running build
running build_ext
building '_simple' extension
swigging simple.i to simple_wrap.c
C:\swigwin\swigwin-3.0.10\swig.exe -python -o simple_wrap.c simple.i
C:\MinGW\bin\gcc.exe -mdll -O -Wall -IC:\Python27\lib\site-packages\numpy\core\include -I. -IC:\Python27\include -IC:\Python27\PC -c simple.cc -o build\temp.win32-2.7\Release\simple.o
C:\MinGW\bin\gcc.exe -mdll -O -Wall -IC:\Python27\lib\sitepackages\numpy\core\include -I. -IC:\Python27\include -IC:\Python27\PC -c simple_wrap.c -o build\temp.win32-2.7\Release\simple_wrap.o
writing build\temp.win32-2.7\Release\_simple.def
C:\MinGW\bin\g++.exe -shared -s build\temp.win32-2.7\Release\simple.o build\temp.win32-2.7\Release\simple_wrap.o build\temp.win32-2.7\Release\_simple.def -LC:\Python27\libs -LC:\Python27\PCbuild -lpython27 -lmsvcr90 -o build\lib.win32-2.7\_simple.pyd
build\temp.win32-2.7\Release\simple_wrap.o:simple_wrap.c:(.text+0xce5): undefined reference to `create_list'
build\temp.win32-2.7\Release\simple_wrap.o:simple_wrap.c:(.text+0x170d): undefined reference to `dot'
collect2.exe: error: ld returned 1 exit status
error: command 'C:\\MinGW\\bin\\g++.exe' failed with exit status 1

I have a terrible feeling that I'm missing something very simple here, but I've managed to successfully compile these identical files in a separate Cygwin environment with no issues (and yes, it is desirable for me to be able to do this in a non-Cygwin environment).

I don't want to choke this question with too much code, but, for reference, here are the files simple.i and setup.py that I'm using.

simple.i:
%module simple
%{
  #define SWIG_FILE_WITH_INIT
  #include "simple.h"
%}

%include "numpy.i"
%init %{
import_array();
%}

%apply (int DIM1, double* INPLACE_ARRAY1) {(int n0, double *a0)};
%apply (int DIM1, double* IN_ARRAY1) {(int n, double *a), (int m, double *b)};
%apply (int DIM1, double* ARGOUT_ARRAY1) {(int size, double *arr)};
%include "simple.h"

setup.py:
from distutils.core import setup, Extension
import numpy
import os

os.environ['CC'] = 'g++';
setup(name='matt_simple_test', version='1.0', ext_modules =[Extension('_simple',['simple.cc', 'simple.i'], include_dirs = [numpy.get_include(),'.'])])

If other code is necessary, I am happy to post them, but again, the other files (simple.cc and simple.h) are used verbatim from here.

So, the question is: can anyone guide me to correct this error?

Upvotes: 3

Views: 391

Answers (1)

J.J. Hakala
J.J. Hakala

Reputation: 6214

In this compilation step the input file is compiled as C++ code and the functions in symbol.cc will be given symbols that are incompatible with C (name mangling).

C:\MinGW\bin\gcc.exe -mdll -O -Wall -IC:\Python27\lib\site-packages\numpy\core\include -I. -IC:\Python27\include -IC:\Python27\PC -c simple.cc -o build\temp.win32-2.7\Release\simple.o

In this compilation step the input file is compiled as C code and the symbols for the functions in symbols.cc are expected to be different.

C:\MinGW\bin\gcc.exe -mdll -O -Wall -IC:\Python27\lib\sitepackages\numpy\core\include -I. -IC:\Python27\include -IC:\Python27\PC -c simple_wrap.c -o build\temp.win32-2.7\Release\simple_wrap.o

One way to fix the problem is to add swig_opts

setup(name='matt_simple_test', version='1.0', 
      ext_modules=[Extension('_simple', ['simple.cc', 'simple.i'],
                   swig_opts=["-c++"],
                   include_dirs = [numpy.get_include(),'.'])])

Another option is to use extern "C" in simple.cc

extern "C" double dot(int n, double *a, int m, double *b)
...
extern "C" void create_list(int size, double *arr)
...

Upvotes: 1

Related Questions