Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Python array to c++ function with SWIG

I have written a good bit of code in python and it works great. But now I'm scaling up the size of the problems that I'm analyzing and python is dreadfully slow. The slow part of the python code is

    for i in range(0,H,1):
       x1 = i - length
       x2 = i + length
       for j in range(0,W,1):
          #print i, ',', j    # check the limits
          y1 = j - length
          y2 = j + length
          IntRed[i,j] = np.mean(RawRed[x1:x2,y1:y2])

With H and W equal to 1024 the function takes around 5 minutes to excute. I've written a simple c++ program/function that performs the same computation and it excutes in less than a second with the same data size.

   double summ = 0;
   double total_num = 0;
   double tmp_num = 0 ;
   int avesize = 2;
   for( i = 0+avesize; i <X-avesize ;i++)
     for(j = 0+avesize;j<Y-avesize;j++)
       {
         // loop through sub region of the matrix
         // if the value is not zero add it to the sum
         // and increment the counter. 
         for( int ii = -2; ii < 2; ii ++)
           {
             int iii = i + ii;
             for( int jj = -2; jj < 2 ; jj ++ )
               {
                 int jjj = j + jj; 
                 tmp_num = gsl_matrix_get(m,iii,jjj); 
                 if(tmp_num != 0 )
                   {
                     summ = summ + tmp_num;
                     total_num++;
                   }


               }
           }
         gsl_matrix_set(Matrix_mean,i,j,summ/total_num);
         summ = 0;
         total_num = 0;

       }

I have some other methods to perform on the 2D array. The one listed is a simple examples.

What I want to do is pass a python 2D array to my c++ function and return a 2D array back to python.

I've read a bit about swig, and have sereached pervious questions, and it seems like it's a possible solution. But I can't seem to figure out what I actually need to do.

Can I get any help? Thanks

like image 384
JMD Avatar asked Mar 09 '11 19:03

JMD


People also ask

How do I use Swig with Python?

By default, SWIG tries to build a very natural Python interface to your C/C++ code. Functions are wrapped as functions, classes are wrapped as classes, and so forth. This section briefly covers the essential aspects of this wrapping. The SWIG %module directive specifies the name of the Python module.

Why is Swig not converting my C++ arguments to Python?

When SWIG does not convert them, it will generate code to obtain them from the C++ layer as if python:cdefaultargs was specified. This will happen if just one argument cannot be converted into a Python equivalent. This occurs typically when the argument is not fully numeric, such as int (1) :

What is Swig_fail in Python?

SWIG_fail is a C macro which when called within the context of SWIG wrapper function, will jump to the error handler code. This will call any cleanup code (freeing any temp variables) and then return from the wrapper function so that the Python interpreter can raise the Python exception.

What is Swig in C++?

What is SWIG In a nutshell, SWIG is a compiler that takes C/C++ declarations and creates a wrapper needed to access those declarations from other languages like Python, Tcl, Ruby etc. It normally required no changes in existing code and create an interface within a minute. Reasons for creating wrapper


1 Answers

You can use arrays as it is described here: Doc - 5.4.5 Arrays, the carray.i or std_vector.i from the SWIG library. I find it easier to work with std::vector from the SWIG library std_vector.i to send a python list to a C++ SWIG extension. Though in your case where optimization matters, it may not be the optimal.

In your case you can define:

test.i

%module test
%{
#include "test.h"
%}

%include "std_vector.i"

namespace std {
%template(Line)  vector < int >;
    %template(Array) vector < vector < int> >;
}   

void print_array(std::vector< std::vector < int > > myarray);

test.h

#ifndef TEST_H__
#define TEST_H__

#include <stdio.h>
#include <vector>

void print_array(std::vector< std::vector < int > > myarray);

#endif /* TEST_H__ */

test.cpp

#include "test.h"

void print_array(std::vector< std::vector < int > > myarray)
{
    for (int i=0; i<2; i++)
        for (int j=0; j<2; j++)
            printf("[%d][%d] = [%d]\n", i, j, myarray[i][j]);
}

If you run the following python code (I used python 2.6.5), you can see that the C++ function can access the python list:

>>> import test
>>> a = test.Array()
>>> a = [[0, 1], [2, 3]]
>>> test.print_array(a)
[0][0] = [0]
[0][1] = [1]
[1][0] = [2]
[1][1] = [3]
like image 64
sherve Avatar answered Oct 23 '22 07:10

sherve