1717#ifndef __eigenpy_details_hpp__
1818#define __eigenpy_details_hpp__
1919
20- #include < boost/python.hpp>
21- #include < Eigen/Core>
22-
23- #include < numpy/numpyconfig.h>
24- #ifdef NPY_1_8_API_VERSION
25- #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
26- #endif
20+ #include " eigenpy/fwd.hpp"
2721
2822#include < numpy/arrayobject.h>
2923#include < iostream>
3024
3125#include " eigenpy/eigenpy.hpp"
3226#include " eigenpy/registration.hpp"
33- #include " eigenpy/exception.hpp"
3427#include " eigenpy/map.hpp"
3528
3629
@@ -58,7 +51,7 @@ namespace eigenpy
5851 { return make ((PyObject*)pyArray,copy); }
5952 bp::object make (PyObject* pyObj, bool copy = false )
6053 {
61- boost::python ::object m
54+ bp ::object m
6255 = pyMatrixType (bp::object (bp::handle<>(pyObj)), bp::object (), copy);
6356 Py_INCREF (m.ptr ());
6457 return m;
@@ -67,16 +60,50 @@ namespace eigenpy
6760 protected:
6861 PyMatrixType ()
6962 {
70- pyModule = boost::python ::import (" numpy" );
63+ pyModule = bp ::import (" numpy" );
7164 pyMatrixType = pyModule.attr (" matrix" );
7265 }
7366
7467 bp::object pyMatrixType;
7568 bp::object pyModule;
7669 };
70+
71+ template <typename MatType>
72+ struct EigenObjectAllocator
73+ {
74+ typedef MatType Type;
75+
76+ static void allocate (PyArrayObject * pyArray, void * storage)
77+ {
78+ typename MapNumpy<MatType>::EigenMap numpyMap = MapNumpy<MatType>::map (pyArray);
79+ new (storage) MatType (numpyMap);
80+ }
81+
82+ static void convert (Type const & mat , PyArrayObject * pyArray)
83+ {
84+ MapNumpy<MatType>::map (pyArray) = mat;
85+ }
86+ };
87+
88+ template <typename MatType>
89+ struct EigenObjectAllocator < eigenpy::Ref<MatType> >
90+ {
91+ typedef eigenpy::Ref<MatType> Type;
92+
93+ static void allocate (PyArrayObject * pyArray, void * storage)
94+ {
95+ typename MapNumpy<MatType>::EigenMap numpyMap = MapNumpy<MatType>::map (pyArray);
96+ new (storage) Type (numpyMap);
97+ }
98+
99+ static void convert (Type const & mat , PyArrayObject * pyArray)
100+ {
101+ MapNumpy<MatType>::map (pyArray) = mat;
102+ }
103+ };
77104
78105 /* --- TO PYTHON -------------------------------------------------------------- */
79- template < typename MatType, typename EquivalentEigenType >
106+ template <typename MatType>
80107 struct EigenToPy
81108 {
82109 static PyObject* convert (MatType const & mat)
@@ -88,139 +115,128 @@ namespace eigenpy
88115
89116 npy_intp shape[2 ] = { R,C };
90117 PyArrayObject* pyArray = (PyArrayObject*)
91- PyArray_SimpleNew (2 , shape, NumpyEquivalentType<T>::type_code);
118+ PyArray_SimpleNew (2 , shape, NumpyEquivalentType<T>::type_code);
92119
93- MapNumpy<EquivalentEigenType >::map ( pyArray) = mat ;
120+ EigenObjectAllocator<MatType >::convert (mat, pyArray);
94121
95122 return PyMatrixType::getInstance ().make (pyArray).ptr ();
96123 }
97124 };
98125
99126 /* --- FROM PYTHON ------------------------------------------------------------ */
100- namespace bp = boost::python;
101-
102- template <typename MatType, int ROWS,int COLS>
103- struct TraitsMatrixConstructor
104- {
105- static MatType & construct (void *storage,int /* r*/ ,int /* c*/ )
106- {
107- return * new (storage) MatType ();
108- }
109- };
110127
111128 template <typename MatType>
112- struct TraitsMatrixConstructor <MatType,Eigen::Dynamic,Eigen::Dynamic>
113- {
114- static MatType & construct (void *storage,int r,int c)
115- {
116- return * new (storage) MatType (r,c);
117- }
118- };
119-
120- template <typename MatType,int R>
121- struct TraitsMatrixConstructor <MatType,R,Eigen::Dynamic>
122- {
123- static MatType & construct (void *storage,int /* r*/ ,int c)
124- {
125- return * new (storage) MatType (R,c);
126- }
127- };
128-
129- template <typename MatType,int C>
130- struct TraitsMatrixConstructor <MatType,Eigen::Dynamic,C>
131- {
132- static MatType & construct (void *storage,int r,int /* c*/ )
133- {
134- return * new (storage) MatType (r,C);
135- }
136- };
137-
138-
139- template <typename MatType,typename EquivalentEigenType>
140129 struct EigenFromPy
141130 {
142131 EigenFromPy ()
143132 {
144133 bp::converter::registry::push_back
145- (reinterpret_cast <void *(*)(_object *)>(&convertible),
146- &construct,bp::type_id<MatType>());
134+ (reinterpret_cast <void *(*)(_object *)>(&convertible),
135+ &construct,bp::type_id<MatType>());
147136 }
148-
137+
149138 // Determine if obj_ptr can be converted in a Eigenvec
150139 static void * convertible (PyArrayObject* obj_ptr)
151140 {
152- typedef typename MatType::Scalar T;
153-
154- if (!PyArray_Check (obj_ptr))
155- {
141+ if (!PyArray_Check (obj_ptr))
142+ {
156143#ifndef NDEBUG
157- std::cerr << " The python object is not a numpy array." << std::endl;
144+ std::cerr << " The python object is not a numpy array." << std::endl;
158145#endif
159- return 0 ;
160- }
161-
146+ return 0 ;
147+ }
148+
149+ if (MatType::IsVectorAtCompileTime)
150+ {
151+ if (PyArray_DIMS (obj_ptr)[0 ] > 1 && PyArray_DIMS (obj_ptr)[1 ] > 1 )
152+ {
153+ #ifndef NDEBUG
154+ std::cerr << " The number of dimension of the object does not correspond to a vector" << std::endl;
155+ #endif
156+ return 0 ;
157+ }
158+
159+ if (((PyArray_DIMS (obj_ptr)[0 ] == 1 ) && (MatType::ColsAtCompileTime == 1 ))
160+ || ((PyArray_DIMS (obj_ptr)[1 ] == 1 ) && (MatType::RowsAtCompileTime == 1 )))
161+ {
162+ #ifndef NDEBUG
163+ if (MatType::ColsAtCompileTime == 1 )
164+ std::cerr << " The object is not a column vector" << std::endl;
165+ else
166+ std::cerr << " The object is not a row vector" << std::endl;
167+ #endif
168+ return 0 ;
169+ }
170+ }
171+
162172 if (PyArray_NDIM (obj_ptr) != 2 )
163- if ( (PyArray_NDIM (obj_ptr) !=1 ) || (! MatType::IsVectorAtCompileTime) )
164- {
173+ {
174+ if ( (PyArray_NDIM (obj_ptr) !=1 ) || (! MatType::IsVectorAtCompileTime) )
175+ {
165176#ifndef NDEBUG
166- std::cerr << " The number of dimension of the object is not correct." << std::endl;
177+ std::cerr << " The number of dimension of the object is not correct." << std::endl;
167178#endif
168- return 0 ;
169- }
170-
171- if ((PyArray_ObjectType (reinterpret_cast <PyObject *>(obj_ptr), 0 )) != NumpyEquivalentType<T>::type_code)
172- {
179+ return 0 ;
180+ }
181+ }
182+
183+ if ((PyArray_ObjectType (reinterpret_cast <PyObject *>(obj_ptr), 0 ))
184+ != NumpyEquivalentType<typename MatType::Scalar>::type_code)
185+ {
173186#ifndef NDEBUG
174- std::cerr << " The internal type as no Eigen equivalent." << std::endl;
187+ std::cerr << " The internal type as no Eigen equivalent." << std::endl;
175188#endif
176- return 0 ;
177- }
189+ return 0 ;
190+ }
178191#ifdef NPY_1_8_API_VERSION
179192 if (!(PyArray_FLAGS (obj_ptr)))
180193#else
181- if (!(PyArray_FLAGS (obj_ptr) & NPY_ALIGNED))
194+ if (!(PyArray_FLAGS (obj_ptr) & NPY_ALIGNED))
182195#endif
183- {
196+ {
184197#ifndef NDEBUG
185- std::cerr << " NPY non-aligned matrices are not implemented." << std::endl;
198+ std::cerr << " NPY non-aligned matrices are not implemented." << std::endl;
186199#endif
187- return 0 ;
188- }
200+ return 0 ;
201+ }
189202
190203 return obj_ptr;
191204 }
192205
193206 // Convert obj_ptr into a Eigenvec
194207 static void construct (PyObject* pyObj,
195- bp::converter::rvalue_from_python_stage1_data* memory)
208+ bp::converter::rvalue_from_python_stage1_data* memory)
196209 {
197210 using namespace Eigen ;
198-
211+
199212 PyArrayObject * pyArray = reinterpret_cast <PyArrayObject*>(pyObj);
200- typename MapNumpy<EquivalentEigenType>::EigenMap numpyMap = MapNumpy<EquivalentEigenType>:: map ( pyArray);
201-
213+ assert (( PyArray_DIMS (pyArray)[ 0 ]<INT_MAX) && ( PyArray_DIMS ( pyArray)[ 1 ]<INT_MAX) );
214+
202215 void * storage = ((bp::converter::rvalue_from_python_storage<MatType>*)
203- ((void *)memory))->storage .bytes ;
204- assert ( (numpyMap.rows ()<INT_MAX) && (numpyMap.cols ()<INT_MAX)
205- && " Map range larger than int ... can never happen." );
206- int r=(int )numpyMap.rows (),c=(int )numpyMap.cols ();
207- EquivalentEigenType & eigenMatrix = // * new(storage) MatType(numpyMap.rows(),numpyMap.cols());
208- TraitsMatrixConstructor<MatType,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime>::construct (storage,r,c);
209- memory->convertible = storage;
216+ ((void *)memory))->storage .bytes ;
217+
218+ EigenObjectAllocator<MatType>::allocate (pyArray,storage);
210219
211- eigenMatrix = numpyMap ;
220+ memory-> convertible = storage ;
212221 }
213222 };
223+
214224#define numpy_import_array () {if (_import_array () < 0 ) {PyErr_Print (); PyErr_SetString (PyExc_ImportError, " numpy.core.multiarray failed to import" ); } }
215225
216226 template <typename MatType,typename EigenEquivalentType>
217227 void enableEigenPySpecific ()
228+ {
229+ enableEigenPySpecific<MatType>();
230+ }
231+
232+ template <typename MatType>
233+ void enableEigenPySpecific ()
218234 {
219235 numpy_import_array ();
220236 if (check_registration<MatType>()) return ;
221237
222- boost::python:: to_python_converter<MatType,EigenToPy<MatType, MatType> >();
223- EigenFromPy<MatType,MatType >();
238+ bp:: to_python_converter<MatType,EigenToPy<MatType> >();
239+ EigenFromPy<MatType>();
224240 }
225241
226242} // namespace eigenpy
0 commit comments