diff --git a/src/details.hpp b/src/details.hpp index 8beec912e7f6445714dadb889ba750fe3709a948..6fe8295d21b6b1109963cf1ef6d0dc217012300d 100644 --- a/src/details.hpp +++ b/src/details.hpp @@ -17,13 +17,7 @@ #ifndef __eigenpy_details_hpp__ #define __eigenpy_details_hpp__ -#include <boost/python.hpp> -#include <Eigen/Core> - -#include <numpy/numpyconfig.h> -#ifdef NPY_1_8_API_VERSION -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#endif +#include "eigenpy/fwd.hpp" #include <numpy/arrayobject.h> #include <iostream> @@ -73,6 +67,40 @@ namespace eigenpy bp::object pyMatrixType; bp::object pyModule; }; + + template<typename MatType> + struct EigenObjectAllocator + { + typedef MatType Type; + + static void allocate(PyArrayObject * pyArray, void * storage) + { + typename MapNumpy<MatType>::EigenMap numpyMap = MapNumpy<MatType>::map(pyArray); + new(storage) MatType(numpyMap); + } + + static void convert(Type const & mat , PyArrayObject * pyArray) + { + MapNumpy<MatType>::map(pyArray) = mat; + } + }; + + template<typename MatType> + struct EigenObjectAllocator< eigenpy::Ref<MatType> > + { + typedef eigenpy::Ref<MatType> Type; + + static void allocate(PyArrayObject * pyArray, void * storage) + { + typename MapNumpy<MatType>::EigenMap numpyMap = MapNumpy<MatType>::map(pyArray); + new(storage) Type(numpyMap); + } + + static void convert(Type const & mat , PyArrayObject * pyArray) + { + MapNumpy<MatType>::map(pyArray) = mat; + } + }; /* --- TO PYTHON -------------------------------------------------------------- */ template<typename MatType> @@ -89,7 +117,7 @@ namespace eigenpy PyArrayObject* pyArray = (PyArrayObject*) PyArray_SimpleNew(2, shape, NumpyEquivalentType<T>::type_code); - MapNumpy<MatType>::map(pyArray) = mat; + EigenObjectAllocator<MatType>::convert(mat,pyArray); return PyMatrixType::getInstance().make(pyArray).ptr(); } @@ -97,16 +125,6 @@ namespace eigenpy /* --- FROM PYTHON ------------------------------------------------------------ */ - template<typename MatType> - struct EigenObjectAllocator - { - static void allocate(PyArrayObject * pyArray, void * storage) - { - typename MapNumpy<MatType>::EigenMap numpyMap = MapNumpy<MatType>::map(pyArray); - new(storage) MatType(numpyMap); - } - }; - template<typename MatType> struct EigenFromPy { @@ -120,8 +138,6 @@ namespace eigenpy // Determine if obj_ptr can be converted in a Eigenvec static void* convertible(PyArrayObject* obj_ptr) { - typedef typename MatType::Scalar T; - if (!PyArray_Check(obj_ptr)) { #ifndef NDEBUG @@ -130,7 +146,31 @@ namespace eigenpy return 0; } + if(MatType::IsVectorAtCompileTime) + { + if(PyArray_DIMS(obj_ptr)[0] > 1 && PyArray_DIMS(obj_ptr)[1] > 1) + { +#ifndef NDEBUG + std::cerr << "The number of dimension of the object does not correspond to a vector" << std::endl; +#endif + return 0; + } + + if(((PyArray_DIMS(obj_ptr)[0] == 1) && (MatType::ColsAtCompileTime == 1)) + || ((PyArray_DIMS(obj_ptr)[1] == 1) && (MatType::RowsAtCompileTime == 1))) + { +#ifndef NDEBUG + if(MatType::ColsAtCompileTime == 1) + std::cerr << "The object is not a column vector" << std::endl; + else + std::cerr << "The object is not a row vector" << std::endl; +#endif + return 0; + } + } + if (PyArray_NDIM(obj_ptr) != 2) + { if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) ) { #ifndef NDEBUG @@ -138,8 +178,10 @@ namespace eigenpy #endif return 0; } + } - if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) != NumpyEquivalentType<T>::type_code) + if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) + != NumpyEquivalentType<typename MatType::Scalar>::type_code) { #ifndef NDEBUG std::cerr << "The internal type as no Eigen equivalent." << std::endl; @@ -178,6 +220,7 @@ namespace eigenpy memory->convertible = storage; } }; + #define numpy_import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); } } template<typename MatType,typename EigenEquivalentType> diff --git a/src/map.hpp b/src/map.hpp index 0c0b633d48d3b181957bd165ec91ff44426f428a..2a2fb4b27f72126db743c4e1ee94756125857660 100644 --- a/src/map.hpp +++ b/src/map.hpp @@ -14,10 +14,9 @@ * with eigenpy. If not, see <http://www.gnu.org/licenses/>. */ -#include <boost/python.hpp> -#include <Eigen/Core> +#include "eigenpy/fwd.hpp" #include <numpy/arrayobject.h> -#include <eigenpy/exception.hpp> +#include "eigenpy/exception.hpp" namespace eigenpy { @@ -30,6 +29,7 @@ namespace eigenpy { typedef MapNumpyTraits<MatType, MatType::IsVectorAtCompileTime> Impl; typedef typename Impl::EigenMap EigenMap; + typedef typename Impl::Stride Stride; static inline EigenMap map( PyArrayObject* pyArray ); }; @@ -45,9 +45,9 @@ namespace eigenpy template<typename MatType> struct MapNumpyTraits<MatType,0> { - typedef Eigen::Stride<Eigen::Dynamic,Eigen::Dynamic> Stride; - typedef Eigen::Map<MatType,0,Stride> EigenMap; - typedef typename MatType::Scalar T; + typedef typename StrideType<MatType>::type Stride; + typedef Eigen::Map<MatType,EIGENPY_DEFAULT_ALIGNMENT_VALUE,Stride> EigenMap; + typedef typename MatType::Scalar Scalar; static EigenMap mapImpl( PyArrayObject* pyArray ) { @@ -63,6 +63,9 @@ namespace eigenpy const long int itemsize = PyArray_ITEMSIZE(pyArray); const int stride1 = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; const int stride2 = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize; + Stride stride(stride2,stride1); + + if( (MatType::RowsAtCompileTime!=R) && (MatType::RowsAtCompileTime!=Eigen::Dynamic) ) @@ -71,17 +74,18 @@ namespace eigenpy && (MatType::ColsAtCompileTime!=Eigen::Dynamic) ) { throw eigenpy::Exception("The number of columns does not fit with the matrix type."); } - T* pyData = reinterpret_cast<T*>(PyArray_DATA(pyArray)); - return EigenMap( pyData, R,C, Stride(stride2,stride1) ); + Scalar* pyData = reinterpret_cast<Scalar*>(PyArray_DATA(pyArray)); + + return EigenMap( pyData, R,C, stride ); } }; template<typename MatType> struct MapNumpyTraits<MatType,1> { - typedef Eigen::InnerStride<Eigen::Dynamic> Stride; - typedef Eigen::Map<MatType,0,Stride> EigenMap; - typedef typename MatType::Scalar T; + typedef typename StrideType<MatType>::type Stride; + typedef Eigen::Map<MatType,EIGENPY_DEFAULT_ALIGNMENT_VALUE,Stride> EigenMap; + typedef typename MatType::Scalar Scalar; static EigenMap mapImpl( PyArrayObject* pyArray ) { @@ -101,8 +105,8 @@ namespace eigenpy && (MatType::MaxSizeAtCompileTime!=Eigen::Dynamic) ) { throw eigenpy::Exception("The number of elements does not fit with the vector type."); } - T* pyData = reinterpret_cast<T*>(PyArray_DATA(pyArray)); - return EigenMap( pyData, R, 1, Stride(stride) ); + Scalar* pyData = reinterpret_cast<Scalar*>(PyArray_DATA(pyArray)); + return EigenMap( pyData, R, Stride(stride) ); } };