Skip to content

Commit d05963c

Browse files
authored
Merge pull request #218 from jcarpent/devel
Handle support of template specialization for exposing new types
2 parents ec232e7 + c3e869d commit d05963c

File tree

10 files changed

+81
-60
lines changed

10 files changed

+81
-60
lines changed

cmake

include/eigenpy/angle-axis.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ namespace eigenpy
3434
}
3535
};
3636

37-
BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxAngleAxis_overload,call<Eigen::AngleAxisd>::isApprox,2,3)
38-
3937
template<typename AngleAxis>
4038
class AngleAxisVisitor
4139
: public bp::def_visitor< AngleAxisVisitor<AngleAxis> >
@@ -48,6 +46,8 @@ namespace eigenpy
4846
typedef typename Eigen::Quaternion<Scalar,0> Quaternion;
4947
typedef Eigen::RotationBase<AngleAxis,3> RotationBase;
5048

49+
BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxAngleAxis_overload,call<AngleAxis>::isApprox,2,3)
50+
5151
public:
5252

5353
template<class PyClass>

include/eigenpy/eigen-allocator.hpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,50 +19,67 @@ namespace eigenpy
1919
template<typename MatType, bool IsVectorAtCompileTime = MatType::IsVectorAtCompileTime>
2020
struct init_matrix_or_array
2121
{
22+
static MatType * run(int rows, int cols, void * storage)
23+
{
24+
if(storage)
25+
return new (storage) MatType(rows,cols);
26+
else
27+
return new MatType(rows,cols);
28+
}
29+
2230
static MatType * run(PyArrayObject * pyArray, void * storage = NULL)
2331
{
2432
assert(PyArray_NDIM(pyArray) == 1 || PyArray_NDIM(pyArray) == 2);
2533

2634
int rows = -1, cols = -1;
27-
if(PyArray_NDIM(pyArray) == 2)
35+
const int ndim = PyArray_NDIM(pyArray);
36+
if(ndim == 2)
2837
{
2938
rows = (int)PyArray_DIMS(pyArray)[0];
3039
cols = (int)PyArray_DIMS(pyArray)[1];
3140
}
32-
else if(PyArray_NDIM(pyArray) == 1)
41+
else if(ndim == 1)
3342
{
3443
rows = (int)PyArray_DIMS(pyArray)[0];
3544
cols = 1;
3645
}
3746

38-
if(storage)
39-
return new (storage) MatType(rows,cols);
40-
else
41-
return new MatType(rows,cols);
47+
return run(rows,cols,storage);
4248
}
4349
};
4450

4551
template<typename MatType>
4652
struct init_matrix_or_array<MatType,true>
4753
{
54+
static MatType * run(int rows, int cols, void * storage)
55+
{
56+
if(storage)
57+
return new (storage) MatType(rows,cols);
58+
else
59+
return new MatType(rows,cols);
60+
}
61+
62+
static MatType * run(int size, void * storage)
63+
{
64+
if(storage)
65+
return new (storage) MatType(size);
66+
else
67+
return new MatType(size);
68+
}
69+
4870
static MatType * run(PyArrayObject * pyArray, void * storage = NULL)
4971
{
50-
if(PyArray_NDIM(pyArray) == 1)
72+
const int ndim = PyArray_NDIM(pyArray);
73+
if(ndim == 1)
5174
{
52-
const int rows_or_cols = (int)PyArray_DIMS(pyArray)[0];
53-
if(storage)
54-
return new (storage) MatType(rows_or_cols);
55-
else
56-
return new MatType(rows_or_cols);
75+
const int size = (int)PyArray_DIMS(pyArray)[0];
76+
return run(size,storage);
5777
}
5878
else
5979
{
6080
const int rows = (int)PyArray_DIMS(pyArray)[0];
6181
const int cols = (int)PyArray_DIMS(pyArray)[1];
62-
if(storage)
63-
return new (storage) MatType(rows,cols);
64-
else
65-
return new MatType(rows,cols);
82+
return run(rows,cols,storage);
6683
}
6784
}
6885
};

include/eigenpy/eigen-from-python.hpp

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,13 @@ namespace eigenpy
275275
memory->convertible = storage->storage.bytes;
276276
}
277277

278-
template<typename MatType>
278+
template<typename MatType, typename _Scalar>
279279
struct EigenFromPy
280280
{
281281
typedef typename MatType::Scalar Scalar;
282282

283283
/// \brief Determine if pyObj can be converted into a MatType object
284-
static void* convertible(PyArrayObject* pyArray);
284+
static void* convertible(PyObject* pyObj);
285285

286286
/// \brief Allocate memory and copy pyObj in the new storage
287287
static void construct(PyObject* pyObj,
@@ -290,12 +290,14 @@ namespace eigenpy
290290
static void registration();
291291
};
292292

293-
template<typename MatType>
294-
void* EigenFromPy<MatType>::convertible(PyArrayObject* pyArray)
293+
template<typename MatType, typename _Scalar>
294+
void* EigenFromPy<MatType,_Scalar>::convertible(PyObject* pyObj)
295295
{
296-
if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
296+
if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyObj)))
297297
return 0;
298298

299+
PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
300+
299301
if(!np_type_is_convertible_into_scalar<Scalar>(EIGENPY_GET_PY_ARRAY_TYPE(pyArray)))
300302
return 0;
301303

@@ -403,15 +405,15 @@ namespace eigenpy
403405
return pyArray;
404406
}
405407

406-
template<typename MatType>
407-
void EigenFromPy<MatType>::construct(PyObject* pyObj,
408-
bp::converter::rvalue_from_python_stage1_data* memory)
408+
template<typename MatType, typename _Scalar>
409+
void EigenFromPy<MatType,_Scalar>::construct(PyObject* pyObj,
410+
bp::converter::rvalue_from_python_stage1_data* memory)
409411
{
410412
eigen_from_py_construct<MatType>(pyObj,memory);
411413
}
412414

413-
template<typename MatType>
414-
void EigenFromPy<MatType>::registration()
415+
template<typename MatType, typename _Scalar>
416+
void EigenFromPy<MatType,_Scalar>::registration()
415417
{
416418
bp::converter::registry::push_back
417419
(reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
@@ -431,7 +433,7 @@ namespace eigenpy
431433

432434
// Add conversion to Eigen::EigenBase<MatType>
433435
typedef Eigen::EigenBase<MatType> EigenBase;
434-
EigenFromPy<EigenBase>::registration();
436+
EigenFromPy<EigenBase,typename MatType::Scalar>::registration();
435437

436438
// Add conversion to Eigen::PlainObjectBase<MatType>
437439
typedef Eigen::PlainObjectBase<MatType> PlainObjectBase;
@@ -464,7 +466,7 @@ namespace eigenpy
464466
};
465467

466468
template<typename MatType>
467-
struct EigenFromPy< Eigen::EigenBase<MatType> > : EigenFromPy<MatType>
469+
struct EigenFromPy< Eigen::EigenBase<MatType>, typename MatType::Scalar > : EigenFromPy<MatType>
468470
{
469471
typedef EigenFromPy<MatType> EigenFromPyDerived;
470472
typedef Eigen::EigenBase<MatType> Base;
@@ -500,13 +502,14 @@ namespace eigenpy
500502
typedef typename MatType::Scalar Scalar;
501503

502504
/// \brief Determine if pyObj can be converted into a MatType object
503-
static void* convertible(PyArrayObject * pyArray)
505+
static void* convertible(PyObject * pyObj)
504506
{
505-
if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
507+
if(!call_PyArray_Check(pyObj))
506508
return 0;
509+
PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
507510
if(!PyArray_ISWRITEABLE(pyArray))
508511
return 0;
509-
return EigenFromPy<MatType>::convertible(pyArray);
512+
return EigenFromPy<MatType>::convertible(pyObj);
510513
}
511514

512515
static void registration()
@@ -524,9 +527,9 @@ namespace eigenpy
524527
typedef typename MatType::Scalar Scalar;
525528

526529
/// \brief Determine if pyObj can be converted into a MatType object
527-
static void* convertible(PyArrayObject * pyArray)
530+
static void* convertible(PyObject * pyObj)
528531
{
529-
return EigenFromPy<MatType>::convertible(pyArray);
532+
return EigenFromPy<MatType>::convertible(pyObj);
530533
}
531534

532535
static void registration()

include/eigenpy/eigen-to-python.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace eigenpy
5050
{
5151
namespace bp = boost::python;
5252

53-
template<typename MatType>
53+
template<typename MatType, typename _Scalar>
5454
struct EigenToPy
5555
{
5656
static PyObject* convert(typename boost::add_reference<typename boost::add_const<MatType>::type>::type mat)
@@ -82,8 +82,8 @@ namespace eigenpy
8282
}
8383
};
8484

85-
template<typename MatType, int Options, typename Stride>
86-
struct EigenToPy< Eigen::Ref<MatType,Options,Stride> >
85+
template<typename MatType, int Options, typename Stride, typename _Scalar>
86+
struct EigenToPy< Eigen::Ref<MatType,Options,Stride>,_Scalar >
8787
{
8888
static PyObject* convert(const Eigen::Ref<MatType,Options,Stride> & mat)
8989
{

include/eigenpy/fwd.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828

2929
namespace eigenpy
3030
{
31-
template<typename MatType> struct EigenToPy;
32-
template<typename MatType> struct EigenFromPy;
31+
template<typename MatType, typename Scalar = typename boost::remove_reference<MatType>::type::Scalar> struct EigenToPy;
32+
template<typename MatType, typename Scalar = typename boost::remove_reference<MatType>::type::Scalar> struct EigenFromPy;
3333
}
3434

3535
#endif // ifndef __eigenpy_fwd_hpp__

include/eigenpy/quaternion.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,6 @@ namespace eigenpy
8888
}
8989
};
9090

91-
BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxQuaternion_overload,call<Eigen::Quaterniond>::isApprox,2,3)
92-
9391
template<typename Quaternion>
9492
class QuaternionVisitor
9593
: public bp::def_visitor< QuaternionVisitor<Quaternion> >
@@ -103,6 +101,8 @@ namespace eigenpy
103101
typedef typename QuaternionBase::Matrix3 Matrix3;
104102

105103
typedef typename QuaternionBase::AngleAxisType AngleAxis;
104+
105+
BOOST_PYTHON_FUNCTION_OVERLOADS(isApproxQuaternion_overload,call<Quaternion>::isApprox,2,3)
106106

107107
public:
108108

include/eigenpy/user-type.hpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ namespace eigenpy
1616
template<typename T, int type_code = NumpyEquivalentType<T>::type_code>
1717
struct SpecialMethods
1818
{
19-
static void copyswap(void * /*dst*/, void * /*src*/, int /*swap*/, void * /*arr*/) {};
20-
static PyObject * getitem(void * /*ip*/, void * /*ap*/) { return NULL; };
21-
static int setitem(PyObject * /*op*/, void * /*ov*/, void * /*ap*/) { return -1; }
22-
static void copyswapn(void * /*dest*/, long /*dstride*/, void * /*src*/,
23-
long /*sstride*/, long /*n*/, int /*swap*/, void * /*arr*/) {};
24-
static npy_bool nonzero(void * /*ip*/, void * /*array*/) { return (npy_bool)false; };
25-
static void dotfunc(void * /*ip0_*/, npy_intp /*is0*/, void * /*ip1_*/, npy_intp /*is1*/,
19+
inline static void copyswap(void * /*dst*/, void * /*src*/, int /*swap*/, void * /*arr*/) /*{}*/;
20+
inline static PyObject * getitem(void * /*ip*/, void * /*ap*/) /*{ return NULL; }*/;
21+
inline static int setitem(PyObject * /*op*/, void * /*ov*/, void * /*ap*/) /*{ return -1; }*/;
22+
inline static void copyswapn(void * /*dest*/, long /*dstride*/, void * /*src*/,
23+
long /*sstride*/, long /*n*/, int /*swap*/, void * /*arr*/) /*{}*/;
24+
inline static npy_bool nonzero(void * /*ip*/, void * /*array*/) /*{ return (npy_bool)false; }*/;
25+
inline static void dotfunc(void * /*ip0_*/, npy_intp /*is0*/, void * /*ip1_*/, npy_intp /*is1*/,
2626
void * /*op*/, npy_intp /*n*/, void * /*arr*/);
2727
// static void cast(void * /*from*/, void * /*to*/, npy_intp /*n*/, void * /*fromarr*/, void * /*toarr*/) {};
2828
};
2929

3030
template<typename T>
3131
struct SpecialMethods<T,NPY_USERDEF>
3232
{
33-
static void copyswap(void * dst, void * src, int swap, void * /*arr*/)
33+
inline static void copyswap(void * dst, void * src, int swap, void * /*arr*/)
3434
{
3535
// std::cout << "copyswap" << std::endl;
3636
if (src != NULL)
@@ -48,7 +48,7 @@ namespace eigenpy
4848
}
4949
}
5050

51-
static PyObject * getitem(void * ip, void * ap)
51+
inline static PyObject * getitem(void * ip, void * ap)
5252
{
5353
// std::cout << "getitem" << std::endl;
5454
PyArrayObject * py_array = static_cast<PyArrayObject *>(ap);
@@ -68,7 +68,7 @@ namespace eigenpy
6868
}
6969
}
7070

71-
static int setitem(PyObject * src_obj, void * dest_ptr, void * array)
71+
inline static int setitem(PyObject * src_obj, void * dest_ptr, void * array)
7272
{
7373
// std::cout << "setitem" << std::endl;
7474
if(array == NULL)
@@ -103,8 +103,8 @@ namespace eigenpy
103103
return 0;
104104
}
105105

106-
static void copyswapn(void * dst, long dstride, void * src, long sstride,
107-
long n, int swap, void * array)
106+
inline static void copyswapn(void * dst, long dstride, void * src, long sstride,
107+
long n, int swap, void * array)
108108
{
109109
// std::cout << "copyswapn" << std::endl;
110110

@@ -122,7 +122,7 @@ namespace eigenpy
122122
}
123123
}
124124

125-
static npy_bool nonzero(void * ip, void * array)
125+
inline static npy_bool nonzero(void * ip, void * array)
126126
{
127127
// std::cout << "nonzero" << std::endl;
128128
static const T ZeroValue = T(0);
@@ -141,8 +141,8 @@ namespace eigenpy
141141
}
142142
}
143143

144-
static void dotfunc(void * ip0_, npy_intp is0, void * ip1_, npy_intp is1,
145-
void * op, npy_intp n, void * /*arr*/)
144+
inline static void dotfunc(void * ip0_, npy_intp is0, void * ip1_, npy_intp is1,
145+
void * op, npy_intp n, void * /*arr*/)
146146
{
147147
T res = T(0);
148148
char *ip0 = (char*)ip0_, *ip1 = (char*)ip1_;

package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0"?>
22
<package format="3">
33
<name>eigenpy</name>
4-
<version>2.5.0</version>
4+
<version>2.6.0</version>
55
<description>Bindings between Numpy and Eigen using Boost.Python</description>
66
<maintainer email="[email protected]">Justin Carpentier</maintainer>
77
<maintainer email="[email protected]">Wolfgang Merkt</maintainer>

unittest/user_type.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ void expose_custom_type(const std::string & name)
8989
.def("__repr__",&Type::print)
9090
;
9191

92-
eigenpy::registerNewType<Type>();
92+
int code = eigenpy::registerNewType<Type>();
93+
std::cout << "code: " << code << std::endl;
9394
eigenpy::registerCommonUfunc<Type>();
9495
}
9596

0 commit comments

Comments
 (0)