diff --git a/include/eigenpy/details.hpp b/include/eigenpy/details.hpp index f431c91ddbb66cc272572d675607998ba95bdd16..dadfe458e2a60b91876547997ebe097e09ff2a1e 100644 --- a/include/eigenpy/details.hpp +++ b/include/eigenpy/details.hpp @@ -79,7 +79,13 @@ namespace eigenpy { if(check_registration<MatType>()) return; + // to-python EigenToPyConverter<MatType>::registration(); +#if EIGEN_VERSION_AT_LEAST(3,2,0) + EigenToPyConverter< Eigen::Ref<MatType> >::registration(); +#endif + + // from-python EigenFromPyConverter<MatType>::registration(); } diff --git a/include/eigenpy/eigen-to-python.hpp b/include/eigenpy/eigen-to-python.hpp index fac253712cbee8f3ee968c6080a5240c04b9bacb..bd89fec522f79a56932f8e0fd33732284f6bb6aa 100644 --- a/include/eigenpy/eigen-to-python.hpp +++ b/include/eigenpy/eigen-to-python.hpp @@ -82,6 +82,36 @@ namespace eigenpy } }; + template<typename MatType, int Options, typename Stride> + struct EigenToPy< Eigen::Ref<MatType,Options,Stride> > + { + static PyObject* convert(const Eigen::Ref<MatType,Options,Stride> & mat) + { + typedef Eigen::Ref<MatType,Options,Stride> EigenRef; + + assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX) + && "Matrix range larger than int ... should never happen." ); + const npy_intp R = (npy_intp)mat.rows(), C = (npy_intp)mat.cols(); + + PyArrayObject* pyArray; + // Allocate Python memory + if( ( ((!(C == 1) != !(R == 1)) && !MatType::IsVectorAtCompileTime) || MatType::IsVectorAtCompileTime) + && NumpyType::getType() == ARRAY_TYPE) // Handle array with a single dimension + { + npy_intp shape[1] = { C == 1 ? R : C }; + pyArray = NumpyAllocator<EigenRef>::allocate(const_cast<EigenRef &>(mat),1,shape); + } + else + { + npy_intp shape[2] = { R,C }; + pyArray = NumpyAllocator<EigenRef>::allocate(const_cast<EigenRef &>(mat),2,shape); + } + + // Create an instance (either np.array or np.matrix) + return NumpyType::make(pyArray).ptr(); + } + }; + template<typename MatType> struct EigenToPyConverter { diff --git a/include/eigenpy/numpy-allocator.hpp b/include/eigenpy/numpy-allocator.hpp index a627c8abbd66dc810d92109a30817552c6675008..9cbeb8a0415c529564bbb2452966f88b947abe32 100644 --- a/include/eigenpy/numpy-allocator.hpp +++ b/include/eigenpy/numpy-allocator.hpp @@ -57,7 +57,7 @@ namespace eigenpy } else { - return NumpyAllocator<MatType>::allocate(mat.derived(),nd,shape); + return NumpyAllocator<MatType>::allocate(mat,nd,shape); } } }; @@ -65,8 +65,33 @@ namespace eigenpy #if EIGEN_VERSION_AT_LEAST(3,2,0) template<typename MatType, int Options, typename Stride> - struct NumpyAllocator<Eigen::Ref<MatType,Options,Stride> > : NumpyAllocator<MatType &> + struct NumpyAllocator<Eigen::Ref<MatType,Options,Stride> > { + typedef Eigen::Ref<MatType,Options,Stride> RefType; + + static PyArrayObject * allocate(RefType & mat, + npy_intp nd, npy_intp * shape) + { + typedef typename RefType::Scalar Scalar; + enum { NPY_ARRAY_MEMORY_CONTIGUOUS = RefType::IsRowMajor ? NPY_ARRAY_CARRAY : NPY_ARRAY_FARRAY }; + + if(NumpyType::sharedMemory()) + { + const int Scalar_type_code = Register::getTypeCode<Scalar>(); + PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(), + static_cast<int>(nd), + shape, + Scalar_type_code, + mat.data(), + NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED); + + return pyArray; + } + else + { + return NumpyAllocator<MatType>::allocate(mat,nd,shape); + } + } }; #endif @@ -88,14 +113,14 @@ namespace eigenpy static_cast<int>(nd), shape, Scalar_type_code, - const_cast<SimilarMatrixType &>(mat.derived()).data(), + const_cast<Scalar *>(mat.data()), NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED); return pyArray; } else { - return NumpyAllocator<MatType>::allocate(mat.derived(),nd,shape); + return NumpyAllocator<MatType>::allocate(mat,nd,shape); } } }; @@ -103,8 +128,34 @@ namespace eigenpy #if EIGEN_VERSION_AT_LEAST(3,2,0) template<typename MatType, int Options, typename Stride> - struct NumpyAllocator<const Eigen::Ref<const MatType,Options,Stride> > : NumpyAllocator<const MatType &> + struct NumpyAllocator<const Eigen::Ref<const MatType,Options,Stride> > { + typedef const Eigen::Ref<const MatType,Options,Stride> RefType; + + template<typename SimilarMatrixType> + static PyArrayObject * allocate(RefType & mat, + npy_intp nd, npy_intp * shape) + { + typedef typename SimilarMatrixType::Scalar Scalar; + enum { NPY_ARRAY_MEMORY_CONTIGUOUS_RO = SimilarMatrixType::IsRowMajor ? NPY_ARRAY_CARRAY_RO : NPY_ARRAY_FARRAY_RO }; + + if(NumpyType::sharedMemory()) + { + const int Scalar_type_code = Register::getTypeCode<Scalar>(); + PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(), + static_cast<int>(nd), + shape, + Scalar_type_code, + const_cast<Scalar *>(mat.data()), + NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED); + + return pyArray; + } + else + { + return NumpyAllocator<MatType>::allocate(mat,nd,shape); + } + } }; #endif