Florian M.
Florian M.

Reputation: 321

Compiling SWIG wrapper for python in Windows

First, thank all of you for all the answer you gave me on this forum the last years, but today I couldn't find a clear answer and so I though It was time to post.

I manage to compile and run a C++ code test5.cpp on my Debian distrib, wrapping it ( maybe it's not the right word) into a python module Amod.py with SWIG ( which necessitate a "translation" file test5.i .I used and import successfully the module for data analysis into other more complex python code ( basically manipulation of numpy array, matplotlib and so on..).

Now I want run the same code on a Windows computer but then python cannot import the module anymore, the librairy file _Amod.so is a .so file, and not .pyd as windows expect. But I cannot find a quick and easy way to recompile it on Windows. I dig the CodeBlocks docs, but its lacunary, i am lost. ( http://wiki.codeblocks.org/index.php?title=Adding_support_for_non_C/C%2B%2B_files_to_the_build_system )

Basically I would like to run the Windows equivalent of the working code below (wich I hope can help beginner is SWIG) :

Compilation :

swig -c++ -python test5.i
g++ -fPIC -c test5.cpp
g++ -fPIC -c test5_wrap.cxx -I/usr/include/python2.7
g++ -shared test5.o test5_wrap.o -o _Amod.so

Wich software and compiler should I use, and how, without losing my time ? (I got CodeBlocks already) Thank you very much.

For information if needed, the test5.i is the following, wrapping C++ array in numpy array, adding some inline (replace functions) for checking purpose (all was dig into swig help with blood and tears):

/* %module module_name is used in compilation as: g++ -shared main.o main_wrap.o -o _module_name.so (with the underscore)*/
%module Amod

%{
/* Put header files here or function declarations like below. The #define SWIG_FILE_WITH_INIT line inserts a macro that specifies that the resulting C file should be built as a python extension, inserting the module init code. check http://www.swig.org/Doc1.3/Python.html#Python_nn3 */
#define SWIG_FILE_WITH_INIT
#include "test5.h"
%}

/* numpy.i and import_array() allow SWIG to manipulate C++ pointer (like double* ivec) like numpy array, because SWIG doesn't know a priori, that the pointer refer to an array. check http://docs.scipy.org/doc/numpy/reference/swig.interface-file.html */

%include "numpy.i"

%init %{
import_array();
%}


/* C++ function arg must fits the typemap directives available in numpy.i. */

%apply (int DIM1, double* INPLACE_ARRAY1) {(int len1, double* ivec),(int len2, double* ovec),(int len3, double* gauss)};
%rename (abel) abel_swig;
%exception abel_swig {
    $action
    if (PyErr_Occurred()) SWIG_fail;
}
%inline %{
void abel_swig(int len1, double* ivec, int len2, double* ovec, int algo, double alpha) {
    if (len1 != len2) {
        PyErr_Format(PyExc_ValueError,"Arrays of lengths (%d,%d) given",len1, len2);
        return;
    }
    memset(ovec, 0, len1*sizeof(double));
    return abel(len1, ivec, len2, ovec, algo, alpha);
}
%}


%rename (convol_gauss) convol_gauss_swig;
%exception convol_gauss_swig {
    $action
    if (PyErr_Occurred()) SWIG_fail;
}
%inline %{
void convol_gauss_swig(int len1, double* ivec, int len2, double* ovec, int len3, double* gauss) {
    if ((len1 != len2)||(len1 != len3)) {
        PyErr_Format(PyExc_ValueError,"Arrays of lengths (%d,%d,%d) given, they must be the same",len1, len2, len3);
        return;
    }
    memset(ovec, 0, len1*sizeof(double));
    return convol_gauss(len1, ivec, len2, ovec, len3, gauss);
}
%}


/* Put header files here or function declarations like below */

%include "test5.h"

and the header test5.h:

#ifndef TEST5_H_INCLUDED
#define TEST5_H_INCLUDED
#include <cstring>
#include <iostream>
#include <cmath>
void convol_gauss(int size, double* ivec, int size2, double* ovec, int size3, double* gauss);
void abel(int len1, double* ivec, int len2, double* ovec, int algo);

#endif // TEST5_H_INCLUDED

Upvotes: 3

Views: 2221

Answers (1)

Florian M.
Florian M.

Reputation: 321

Ok, I managed to do it.

1- Take care that you .i files are encoded in utf-8, as it prevented swig to compile if Python as a different encoding.( #error Must use Python with unicode enabled )

2- Download swig for Windows on www.swig.org and installing MinGW

3- type in cmd or Powershell

swig -c++ -python test5.i
g++ -c -Wall test5.cpp
g++ -c -Wall test5_wrap.cxx -I C:\Python27\include -I C:\Python27\Lib\site-packages\numpy\core\include\
g++ -Wall -shared -I C:\Python27\include -I C:\Python27\Lib\site-packages\numpy\core\include\ test5.o test5_wrap.o -o _Amod.pyd -L C:/Python27/libs/ -lpython27

-I C:\Python27\Lib\site-packages\numpy\core\include\ solve the Error : fatal error : numpy\arrayobject.h no such file or directory

-L C:/Python27/libs/ -lpython27 solve the Error : undefined reference to _imp__Py...

Contrary to the Linux compilation, the library C:/Python27/libs/python27.lib has to be carefully linked, as well as the directores of the headers (C:\Python27\include and for numpy C:\Python27\Lib\site-packages\numpy\core\include) Hope it can helps, but I don't have the feeling it's a very clean job. See this previous post considering the errors I met.

Upvotes: 2

Related Questions