Integrating SWIG and NumPy

C is a widespread programming language developed around 1970. Various C dialects exist and C has influenced other programming languages. C is not object-oriented. This led to the creation of C++, which is an object-oriented language with C features, since C is a subset of C++. C and C++ are compiled languages. We need to compile source code to create so-called object files. After that, we must link the object files to create dynamically shared libraries.

The good thing about integrating C and Python is that a lot of options are available to us. The first option is Simplified Wrapper and Interface Generator (SWIG). SWIG adds an additional step in the development process, which is the generation of glue code between Python and C (or C++). Download SWIG from http://www.swig.org/download.html. At the time of writing, the most current SWIG version was 3.0.2. A prerequisite to installing SWIG is to install Perl Compatible Regular Expressions (PCRE). PCRE is a C regular expressions library. Download PCRE from http://www.pcre.org/. The most current PCRE version at the time of writing was 8.35. After unpacking PCRE, run the following commands:

$ ./configure
$ make
$ make install

The last command in the preceding snippet requires root or sudo access. We can install SWIG with the same commands. We start by writing a header file containing function definitions. Write a header file, which defines the following function:

double sum_rain(int* rain, int len);

We will use the preceding function to sum the rain amount values we analyzed in the previous chapter. Please refer to the sum_rain.h file in this book's code bundle. The function is implemented in the sum_rain.cpp file in this book's code bundle:

double sum_rain(int* rain, int len) {

  double sum = 0.;

  for (int i = 0; i < len; i++){
    if(rain[i] == -1) {
       sum += 0.025;
    } else {
      sum += 0.1 * rain[i];
    }
  }

  return sum;
}

Define the following SWIG interface file (refer to the sum_rain.i file in this book's code bundle):

%module sum_rain

%{
  #define SWIG_FILE_WITH_INIT
  #include "sum_rain.h"
%}

%include "/tmp/numpy.i"

%init %{
  import_array();
%}

%apply (int* IN_ARRAY1, int DIM1) {(int* rain, int len)};

%include "sum_rain.h"

The preceding code depends on the numpy.i interface file, which can be found at https://github.com/numpy/numpy/blob/master/tools/swig/numpy.i. In this example, the file was placed in the /tmp directory, but we can put this file almost anywhere. Generate the SWIG glue code with the following command:

$ swig -c++ -python sum_rain.i

The preceding step creates a sum_rain_wrap.cxx file. Compile the sum_rain.cpp file as follows:

$ g++ -O2 -fPIC -c sum_rain.cpp –I<Python headers dir>

In the previous command, we need to specify the actual Python C headers directory. We can find it with the following command:

$ python-config –includes

Therefore, we could have also compiled with the following command:

$ g++ -O2 -fPIC -c sum_rain.cpp –I $(python-config –includes)

The location of this directory will differ depending on Python version and operating system (it would be something like /usr/include/python2.7). Compile the generated SWIG wrapper file as follows:

$ g++ -O2 -fPIC -c sum_rain_wrap.cxx –I<Python headers dir>  -I<numpy-dir>/core/include/

The preceding command depends on the location of the installed NumPy. Locate it from the Python shell as follows:

$ python
>>> import numpy as np
>>> np.__file__

The string printed on the screen should contain the Python version, site-packages, and end in __init__.pyc. If we strip the last part, we should have the NumPy directory. Alternatively, we can use the following code:

>>> from imp import find_module
>>> find_module('numpy')

The final step is to link the object files created by compiling:

$ g++ -lpython -dynamiclib sum_rain.o sum_rain_wrap.o -o _sum_rain.so

The preceding steps will work differently on other operating systems, such as Windows, unless we use Cygwin. It is recommended to ask for help on the SWIG user mailing lists (http://www.swig.org/mail.html) or StackOverflow, if required.

Test the created library with the swig_demo.py file in this book's code bundle:

from _sum_rain import *
import numpy as np

rain = np.load('rain.npy')
print "Swig", sum_rain(rain)
rain = .1 * rain
rain[rain < 0] = .025
print "Numpy", rain.sum()

If everything went fine and we didn't confuse Python installations, the following lines will be printed:

Swig 85291.55
Numpy 85291.55
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.22.164