Giter VIP home page Giter VIP logo

swig-eigen-numpy's Introduction

Eigen to Numpy with Swig

Build Status

Introduction

This package exists as a demonstration of some of the tools I've been playing with to wrap C++ libraries which use Eigen Matrix types in Python (using numpy arrays). Specifically, it demonstrates:

  • Wrapping a C++ class in a Python class
  • Passing numpy arrays to and from C++ methods which accept and return Eigen Matrix types
  • Adding additional Python-defined methods to a C++ class
  • Calling templated C++ functions from Python.
  • Calling C++ methods which take Eigen::Ref arguments from Python
  • Support for Python 2.7 and Python 3

To show this off, I've written a C++ function which uses Eigen's LU module to invert matrices. This is a trivially simple example, but hopefully it will make someone's life a little easier down the road.

Requirements

You'll need, at the very least:

  • cmake
  • swig
  • a c/c++ compiler for your system

On OSX, you can follow the instructions from Homebrew to install a compiler and use Homebrew to install the cmake swig packages. On Ubuntu, you can sudo apt-get install cmake swig.

If you don't have a copy of eigen3 installed, one will be automatically downloaded and built for you. If you don't want that, just install the eigen3 package yourself. In Homebrew it's called eigen and in apt-get it's called libeigen3-dev.

Building

This project is entirely configured using CMake, so building should be pretty easy. Just:

mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../install
make
make install

Nothing should get installed into your system; instead, the inverter library will get put in install/lib/. If you want to install globally, then you can just remove the -DCMAKE_INSTALL_PREFIX=../install argument.

Using the python bindings

You'll need to make sure that the inverter shared library is accessible to your system at runtime. If you installed globally (without the -DCMAKE_INSTALL_PREFIX=../install argument), then you're all set. Otherweise, on OSX, you can do:

export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:/path/to/wherever/you/put/swig-eigen-numpy/install/lib"

Or on Linux:

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/path/to/wherever/you/put/swig-eigen-numpy/install/lib"

That will only affect the current instance of your terminal. To make that change permanent, put that line inside your ~/.bashrc file.

The python bindings are demonstrated in python/test_inverter.py. To run it, just do:

cd python
python test_inverter.py

Structure of this repo

src

contains our c++ library, header, and a test executable

python

contains the main swig interface file and our python source code

swigmake/swig

contains general-purpose swig interface files for eigen and numpy

swigmake/cmake

contains some helper scripts for cmake to find the eigen and numpy libraries

Python 3 support

This project should build and run correctly on Python 2 or Python 3. To change python versions, you can add another argument to cmake:

mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../install -DPYTHON_EXECUTABLE=`which python3`
make
make install
cd ../python
python3 test_inverter.py

In the above code I've told cmake to build with python3 instead of my default python2.

swig-eigen-numpy's People

Contributors

rdeits avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swig-eigen-numpy's Issues

Some question about c struct array to numpy array with swig

Hello, sir

in order to speed up the compuation of python, I chose to use matlab's coder toolbox to convert matlab to c/c++ code, so as not to rely on matlab runtime.

I just recently learned

swig through coder-swig.View coder-swig on File Exchange

This package converts wrap MATLAB Coder generated C and C++ code to python code with swig.

But I found it is too complicated to use the function in the c dll file with numpy , as shown in the code example.

I have many questions about the i files about swig,Can you help me?

Here is some code changed from the third example of the coder-swig package.
03-timestwo-dynamic-size.zip

Firsr, the Code generation for function 'timestwo' is shown as below.

/* Function Definitions in timestwo.h*/
void timestwo(const emxArray_real_T *x, emxArray_real_T *y)

Here x is input array ,y is output array.

the emxArray is a struct is show as below.

/* Type Definitions in timestwo_types.h*/
#ifndef struct_emxArray_real_T
#define struct_emxArray_real_T

struct emxArray_real_T
{
  double *data;
  int *size;
  int allocatedSize;
  int numDimensions;
  boolean_T canFreeData;
};

#endif    

I have write an i file to wrap emxArray_real_T for numpy array.

It seems not work.Can you help me to check it?

Or is there a simple or clever way to convert emx array to numpy array, like convert eigen matirx to numpy wieth eigen.i file?

%module timestwo
%{
#define SWIG_FILE_WITH_INIT
#include "codegen/dll/timestwo/timestwo_types.h"
#include "codegen/dll/timestwo/timestwo.h"
#include "codegen/dll/timestwo/timestwo_emxAPI.h"
#include "codegen/dll/timestwo/timestwo_initialize.h"
#include "codegen/dll/timestwo/timestwo_terminate.h"
%}
%include "carrays.i"
%array_class(double, doubleArray);
//%array_class(int, intArray);

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

//%apply (double* IN_ARRAY2, int DIM1, int DIM2) {(double *data, int rows, int cols)};

/* Generate includes for required headers */

#include "codegen/dll/timestwo/timestwo_types.h"
#include "codegen/dll/timestwo/timestwo.h"
#include "codegen/dll/timestwo/timestwo_emxAPI.h"
#include "codegen/dll/timestwo/timestwo_initialize.h"
#include "codegen/dll/timestwo/timestwo_terminate.h"

/* numpy array as input */
%typemap(in)
    (emxArray_real_T*)
    (PyArrayObject* array=NULL, int is_new_object=0)
{
    array = (PyArrayObject*) obj_to_array_contiguous_allow_conversion($input, NPY_DOUBLE, &is_new_object);
    if (!array) SWIG_fail;
    int numDimensions;
	numDimensions=array_numdims(array)	;
	int*size= (int*)malloc(numDimensions * sizeof(int));
	int n_elems=1;
	for (int i=0;i<numDimensions;i++)
	{
	size[i]=array_size(array, i);
	n_elems*=size[i];	
	}
    $1 = emxCreateND_real_T(numDimensions, size);
    memcpy($1->data, array_data(array), n_elems);
}

/* numpy array as output */
%typemap(out) 
(emxArray_real_T*)
{
    $result = NULL;
    if ($1)
    {	
            int numDimensions= $1->numDimensions;
            npy_intp dims =  $1->size ;
            PyObject* res_array = PyArray_SimpleNewFromData(numDimensions, dims, NPY_DOUBLE,$1->data);
            $result = SWIG_Python_AppendOutput($result, res_array);
            emxDestroyArray_real_T($1);
    }

    if($result == NULL)
    {
        PyErr_SetString(PyExc_RuntimeError, "Result not yet implemented");
    }
}


%typemap(freearg)
    (emxArray_real_T*)
{
  if (is_new_object$argnum && array$argnum) Py_DECREF(array$argnum);
  emxDestroyArray_real_T($1);
}



/* Destructor for emxArray_real_T  */
%extend emxArray_real_T {
    ~emxArray_real_T() {
        emxDestroyArray_real_T($self);
    }
}

/* Tell SWIG about allocators */
//%newobject emxCreate_real_T;
//%newobject emxCreateWrapper_real_T;
//%newobject emxCreateND_real_T;
//%newobject emxCreateWrapperND_real_T;

/* Parse necessary headers */
%include codegen/dll/timestwo/timestwo_types.h
%include codegen/dll/timestwo/timestwo.h
%include codegen/dll/timestwo/timestwo_emxAPI.h
%include codegen/dll/timestwo/timestwo_initialize.h
%include codegen/dll/timestwo/timestwo_terminate.h

build error

Am getting the following error when running 'make'

cueball:build chrisfowler$ cmake .. -DCMAKE_INSTALL_PREFIX=../install
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/chrisfowler/dev/swig-eigen-numpy/build
cueball:build chrisfowler$ make
[ 28%] Built target inverter
[ 57%] Built target testInverter
[ 71%] Building CXX object python/CMakeFiles/_inverterWrapperPython.dir/inverter_wrapperPYTHON_wrap.cxx.o
/Users/chrisfowler/dev/swig-eigen-numpy/build/python/inverter_wrapperPYTHON_wrap.cxx:4780:12: error: explicit specialization of non-template struct
      'traits_reserve'
    struct traits_reserve<std::vector<T> > {
           ^             ~~~~~~~~~~~~~~~~~
1 error generated.
make[2]: *** [python/CMakeFiles/_inverterWrapperPython.dir/inverter_wrapperPYTHON_wrap.cxx.o] Error 1
make[1]: *** [python/CMakeFiles/_inverterWrapperPython.dir/all] Error 2
make: *** [all] Error 2
cueball:build chrisfowler$

Eigen3 was installed automatically and other dependencies installed with 'brew'

Am on Mac Sierra 10.12.6.

Am new to integrating c++ and python so reaching out for any assistance you can give.

Thankyou

Merge in latest version of swigmake

This works with Eigen 3.3 if the swigmake directory is replaced with the contents of your swigmake repo.

It looks like pull_subs.sh is supposed to automate this process, but it is creating merge conflicts for me.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.