From 52106de3644c78cdf3e55fea0b3acb9c41be1d23 Mon Sep 17 00:00:00 2001 From: Justin Carpentier <justin.carpentier@inria.fr> Date: Sat, 22 Feb 2020 19:58:20 +0100 Subject: [PATCH] core: add converter to python for Eigen::Matrix --- include/eigenpy/details.hpp | 1 - include/eigenpy/eigen-to-python.hpp | 109 ++++++++++++++++++---------- 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/include/eigenpy/details.hpp b/include/eigenpy/details.hpp index 6b15de6c..484e1b98 100644 --- a/include/eigenpy/details.hpp +++ b/include/eigenpy/details.hpp @@ -22,7 +22,6 @@ #include "eigenpy/map.hpp" #include "eigenpy/exception.hpp" - namespace boost { namespace python { namespace detail { template<class MatType> diff --git a/include/eigenpy/eigen-to-python.hpp b/include/eigenpy/eigen-to-python.hpp index 0696eea1..cc990519 100644 --- a/include/eigenpy/eigen-to-python.hpp +++ b/include/eigenpy/eigen-to-python.hpp @@ -8,53 +8,88 @@ #include "eigenpy/fwd.hpp" #include "eigenpy/numpy-type.hpp" #include "eigenpy/eigen-allocator.hpp" +#include "eigenpy/numpy-allocator.hpp" + +#include <boost/type_traits.hpp> + +namespace boost { namespace python { + + template<typename MatrixRef, class MakeHolder> + struct to_python_indirect_eigen + { + template <class U> + inline PyObject* operator()(U const& mat) const + { + return eigenpy::EigenToPy<MatrixRef>::convert(const_cast<U&>(mat)); + } + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + inline PyTypeObject const* + get_pytype()const + { + return converter::registered_pytype<MatrixRef>::get_pytype(); + } +#endif + }; + + template <typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime, int Options, int MaxRowsAtCompileTime, int MaxColsAtCompileTime, class MakeHolder> + struct to_python_indirect<Eigen::Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,Options,MaxRowsAtCompileTime,MaxColsAtCompileTime>&,MakeHolder> + : to_python_indirect_eigen<Eigen::Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,Options,MaxRowsAtCompileTime,MaxColsAtCompileTime>&,MakeHolder> + { + }; + + template <typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime, int Options, int MaxRowsAtCompileTime, int MaxColsAtCompileTime, class MakeHolder> + struct to_python_indirect<const Eigen::Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,Options,MaxRowsAtCompileTime,MaxColsAtCompileTime>&,MakeHolder> + : to_python_indirect_eigen<const Eigen::Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,Options,MaxRowsAtCompileTime,MaxColsAtCompileTime>&,MakeHolder> + { + }; + +}} namespace eigenpy { namespace bp = boost::python; - template<typename MatType> - struct EigenToPy + template<typename MatType> + struct EigenToPy + { + static PyObject* convert(typename boost::add_reference<typename boost::add_const<MatType>::type>::type mat) { - static PyObject* convert(MatType const & mat) + typedef typename boost::remove_const<typename boost::remove_reference<MatType>::type>::type MatrixDerived; + + 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)) && !MatrixDerived::IsVectorAtCompileTime) || MatrixDerived::IsVectorAtCompileTime) + && NumpyType::getType() == ARRAY_TYPE) // Handle array with a single dimension { - typedef typename MatType::Scalar Scalar; - 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 = (PyArrayObject*) PyArray_SimpleNew(1, shape, - NumpyEquivalentType<Scalar>::type_code); - } - else - { - npy_intp shape[2] = { R,C }; - pyArray = (PyArrayObject*) PyArray_SimpleNew(2, shape, - NumpyEquivalentType<Scalar>::type_code); - } - - // Copy data - EigenAllocator<MatType>::copy(mat,pyArray); - - // Create an instance (either np.array or np.matrix) - return NumpyType::getInstance().make(pyArray).ptr(); + npy_intp shape[1] = { C == 1 ? R : C }; + pyArray = NumpyAllocator<MatType>::allocate(const_cast<MatrixDerived &>(mat.derived()), + 1,shape); } - }; - - template<typename MatType> - struct EigenToPyConverter - { - static void registration() + else { - bp::to_python_converter<MatType,EigenToPy<MatType> >(); + npy_intp shape[2] = { R,C }; + pyArray = NumpyAllocator<MatType>::allocate(const_cast<MatrixDerived &>(mat.derived()), + 2,shape); } - }; + + // Create an instance (either np.array or np.matrix) + return NumpyType::make(pyArray).ptr(); + } + }; + + template<typename MatType> + struct EigenToPyConverter + { + static void registration() + { + bp::to_python_converter<MatType,EigenToPy<MatType> >(); + } + }; #if EIGEN_VERSION_AT_LEAST(3,2,0) template<typename MatType> -- GitLab