dellaert 2016-01-20 09:28:30 -08:00
parent c77997fbb1
commit eb5d026a4a
3 changed files with 82 additions and 50 deletions

View File

@ -12,8 +12,17 @@
#ifndef NUMPY_EIGEN_CONVERTER_HPP
#define NUMPY_EIGEN_CONVERTER_HPP
#include "boost_python_headers.hpp"
#include <iostream>
#include <numpy_eigen/boost_python_headers.hpp>
//#include <iostream>
#include "numpy/numpyconfig.h"
#ifdef NPY_1_7_API_VERSION
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#define NPE_PY_ARRAY_OBJECT PyArrayObject
#else
//TODO Remove this as soon as support for Numpy version before 1.7 is dropped
#define NPE_PY_ARRAY_OBJECT PyObject
#endif
#define PY_ARRAY_UNIQUE_SYMBOL NP_Eigen_AS
#include <numpy/arrayobject.h>
@ -93,7 +102,7 @@ struct NumpyEigenConverter
npy_intp dimensions[1];
dimensions[0] = M.size();
P = PyArray_SimpleNew(1, dimensions, TypeToNumPy<scalar_t>::NpyType);
numpyTypeDemuxer< CopyEigenToNumpyVector<const matrix_t> >(&M,P);
numpyTypeDemuxer< CopyEigenToNumpyVector<const matrix_t> >(&M, reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(P));
}
else
{
@ -102,7 +111,7 @@ struct NumpyEigenConverter
dimensions[0] = M.rows();
dimensions[1] = M.cols();
P = PyArray_SimpleNew(2, dimensions, TypeToNumPy<scalar_t>::NpyType);
numpyTypeDemuxer< CopyEigenToNumpyMatrix<const matrix_t> >(&M,P);
numpyTypeDemuxer< CopyEigenToNumpyMatrix<const matrix_t> >(&M, reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(P));
}
// incrementing the reference seems to cause a memory leak.
@ -131,7 +140,7 @@ struct NumpyEigenConverter
return valid;
}
static void checkMatrixSizes(PyObject * obj_ptr)
static void checkMatrixSizes(NPE_PY_ARRAY_OBJECT * obj_ptr)
{
int rows = PyArray_DIM(obj_ptr, 0);
int cols = PyArray_DIM(obj_ptr, 1);
@ -145,7 +154,7 @@ struct NumpyEigenConverter
}
}
static void checkRowVectorSizes(PyObject * obj_ptr, int cols)
static void checkRowVectorSizes(NPE_PY_ARRAY_OBJECT * obj_ptr, int cols)
{
if(!isDimensionValid(cols, ColsAtCompileTime, MaxColsAtCompileTime))
{
@ -154,7 +163,7 @@ struct NumpyEigenConverter
}
}
static void checkColumnVectorSizes(PyObject * obj_ptr, int rows)
static void checkColumnVectorSizes(NPE_PY_ARRAY_OBJECT * obj_ptr, int rows)
{
// Check if the type can accomidate one column.
if(ColsAtCompileTime == Eigen::Dynamic || ColsAtCompileTime == 1)
@ -173,7 +182,7 @@ struct NumpyEigenConverter
}
static void checkVectorSizes(PyObject * obj_ptr)
static void checkVectorSizes(NPE_PY_ARRAY_OBJECT * obj_ptr)
{
int size = PyArray_DIM(obj_ptr, 0);
@ -206,8 +215,10 @@ struct NumpyEigenConverter
return 0;
}
NPE_PY_ARRAY_OBJECT * array_ptr = reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(obj_ptr);
// Check the type of the array.
int npyType = PyArray_ObjectType(obj_ptr, 0);
int npyType = getNpyType(array_ptr);
if(!TypeToNumPy<scalar_t>::canConvert(npyType))
{
@ -219,7 +230,7 @@ struct NumpyEigenConverter
// Check the array dimensions.
int nd = PyArray_NDIM(obj_ptr);
int nd = PyArray_NDIM(array_ptr);
if(nd != 1 && nd != 2)
{
@ -228,12 +239,12 @@ struct NumpyEigenConverter
if(nd == 1)
{
checkVectorSizes(obj_ptr);
checkVectorSizes(array_ptr);
}
else
{
// Two-dimensional matrix type.
checkMatrixSizes(obj_ptr);
checkMatrixSizes(array_ptr);
}
@ -265,10 +276,17 @@ struct NumpyEigenConverter
matrix_t & M = *Mp;
int nd = PyArray_NDIM(obj_ptr);
if (!PyArray_Check(obj_ptr))
{
THROW_TYPE_ERROR("construct is only defined for numpy array and matrix types");
}
NPE_PY_ARRAY_OBJECT * array_ptr = reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(obj_ptr);
int nd = PyArray_NDIM(array_ptr);
if(nd == 1)
{
int size = PyArray_DIM(obj_ptr, 0);
int size = PyArray_DIM(array_ptr, 0);
// This is a vector type
if(RowsAtCompileTime == 1)
{
@ -280,15 +298,15 @@ struct NumpyEigenConverter
// Column Vector
M.resize(size,1);
}
numpyTypeDemuxer< CopyNumpyToEigenVector<matrix_t> >(&M,obj_ptr);
numpyTypeDemuxer< CopyNumpyToEigenVector<matrix_t> >(&M, array_ptr);
}
else
{
int rows = PyArray_DIM(obj_ptr, 0);
int cols = PyArray_DIM(obj_ptr, 1);
int rows = PyArray_DIM(array_ptr, 0);
int cols = PyArray_DIM(array_ptr, 1);
M.resize(rows,cols);
numpyTypeDemuxer< CopyNumpyToEigenMatrix<matrix_t> >(&M,obj_ptr);
numpyTypeDemuxer< CopyNumpyToEigenMatrix<matrix_t> >(&M, array_ptr);
}

View File

@ -9,16 +9,16 @@ struct CopyNumpyToEigenMatrix
typedef typename matrix_t::Scalar scalar_t;
template<typename T>
void exec(EIGEN_T * M_, PyObject * P_)
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
{
// Assumes M is already initialized.
for(int r = 0; r < M_->rows(); r++)
{
for(int c = 0; c < M_->cols(); c++)
{
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
(*M_)(r,c) = static_cast<scalar_t>(*p);
}
for(int c = 0; c < M_->cols(); c++)
{
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
(*M_)(r,c) = static_cast<scalar_t>(*p);
}
}
}
@ -31,16 +31,16 @@ struct CopyEigenToNumpyMatrix
typedef typename matrix_t::Scalar scalar_t;
template<typename T>
void exec(EIGEN_T * M_, PyObject * P_)
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
{
// Assumes M is already initialized.
for(int r = 0; r < M_->rows(); r++)
{
for(int c = 0; c < M_->cols(); c++)
{
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
*p = static_cast<T>((*M_)(r,c));
}
for(int c = 0; c < M_->cols(); c++)
{
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
*p = static_cast<T>((*M_)(r,c));
}
}
}
@ -53,13 +53,13 @@ struct CopyEigenToNumpyVector
typedef typename matrix_t::Scalar scalar_t;
template<typename T>
void exec(EIGEN_T * M_, PyObject * P_)
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
{
// Assumes M is already initialized.
for(int i = 0; i < M_->size(); i++)
{
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
*p = static_cast<T>((*M_)(i));
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
*p = static_cast<T>((*M_)(i));
}
}
@ -73,13 +73,13 @@ struct CopyNumpyToEigenVector
typedef typename matrix_t::Scalar scalar_t;
template<typename T>
void exec(EIGEN_T * M_, PyObject * P_)
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
{
// Assumes M is already initialized.
for(int i = 0; i < M_->size(); i++)
{
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
(*M_)(i) = static_cast<scalar_t>(*p);
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
(*M_)(i) = static_cast<scalar_t>(*p);
}
}
@ -91,10 +91,11 @@ struct CopyNumpyToEigenVector
// Crazy syntax in this function was found here:
// http://stackoverflow.com/questions/1840253/c-template-member-function-of-template-class-called-from-template-function/1840318#1840318
template< typename FUNCTOR_T>
inline void numpyTypeDemuxer(typename FUNCTOR_T::matrix_t * M, PyObject * P)
inline void numpyTypeDemuxer(typename FUNCTOR_T::matrix_t * M, NPE_PY_ARRAY_OBJECT * P)
{
FUNCTOR_T f;
int npyType = PyArray_ObjectType(P, 0);
int npyType = getNpyType(P);
switch(npyType)
{
case NPY_BOOL:

View File

@ -1,12 +1,12 @@
#ifndef NUMPY_EIGEN_TYPE_TRAITS_HPP
#define NUMPY_EIGEN_TYPE_TRAITS_HPP
#define THROW_TYPE_ERROR(msg) \
{ \
std::stringstream type_error_ss; \
type_error_ss << msg; \
PyErr_SetString(PyExc_TypeError, type_error_ss.str().c_str()); \
throw boost::python::error_already_set(); \
#define THROW_TYPE_ERROR(msg) \
{ \
std::stringstream type_error_ss; \
type_error_ss << msg; \
PyErr_SetString(PyExc_TypeError, type_error_ss.str().c_str()); \
throw boost::python::error_already_set(); \
}
@ -99,6 +99,19 @@ template<> struct TypeToNumPy<double>
};
inline int getNpyType(PyObject * obj_ptr){
return PyArray_ObjectType(obj_ptr, 0);
}
#ifdef NPY_1_7_API_VERSION
inline int getNpyType(PyArrayObject * obj_ptr){
PyArray_Descr * descr = PyArray_MinScalarType(obj_ptr);
if (descr == NULL){
THROW_TYPE_ERROR("Unsupported type: PyArray_MinScalarType returned null!");
}
return descr->type_num;
}
#endif
inline const char * npyTypeToString(int npyType)
{
@ -157,18 +170,18 @@ inline const char * npyTypeToString(int npyType)
}
}
inline std::string npyArrayTypeString(PyObject * obj_ptr)
inline std::string npyArrayTypeString(NPE_PY_ARRAY_OBJECT * obj_ptr)
{
std::stringstream ss;
int nd = PyArray_NDIM(obj_ptr);
ss << "numpy.array<" << npyTypeToString(PyArray_ObjectType(obj_ptr, 0)) << ">[";
ss << "numpy.array<" << npyTypeToString(getNpyType(obj_ptr)) << ">[";
if(nd > 0)
{
ss << PyArray_DIM(obj_ptr, 0);
for(int i = 1; i < nd; i++)
{
ss << ", " << PyArray_DIM(obj_ptr, i);
}
{
ss << ", " << PyArray_DIM(obj_ptr, i);
}
}
ss << "]";
return ss.str();