Skip to content

Commit fc8c28c

Browse files
authored
Merge pull request #191 from jcarpent/devel
Sync submodule CMake + enforce testing
2 parents 6f29b9e + 5de17a9 commit fc8c28c

File tree

10 files changed

+166
-99
lines changed

10 files changed

+166
-99
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ jobs:
4747
-DPYTHON_EXECUTABLE=%CONDA_PREFIX%\python.exe ^
4848
..
4949
cmake --build . --config Release --target install
50+
ctest --output-on-failure

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ SET(${PROJECT_NAME}_SOURCES
150150
src/exception.cpp
151151
src/eigenpy.cpp
152152
src/numpy.cpp
153+
src/numpy-type.cpp
153154
src/matrix-float.cpp
154155
src/matrix-complex-float.cpp
155156
src/matrix-complex-double.cpp

include/eigenpy/eigen-from-python.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ namespace eigenpy
285285
template<typename MatType>
286286
void* EigenFromPy<MatType>::convertible(PyArrayObject* pyArray)
287287
{
288-
if(!PyArray_Check(pyArray))
288+
if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
289289
return 0;
290290

291291
if(!np_type_is_convertible_into_scalar<Scalar>(EIGENPY_GET_PY_ARRAY_TYPE(pyArray)))
@@ -476,7 +476,7 @@ namespace eigenpy
476476
/// \brief Determine if pyObj can be converted into a MatType object
477477
static void* convertible(PyArrayObject * pyArray)
478478
{
479-
if(!PyArray_Check(pyArray))
479+
if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
480480
return 0;
481481
if(!PyArray_ISWRITEABLE(pyArray))
482482
return 0;

include/eigenpy/numpy-type.hpp

Lines changed: 16 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "eigenpy/fwd.hpp"
99
#include "eigenpy/scalar-conversion.hpp"
1010

11-
#include <patchlevel.h> // For PY_MAJOR_VERSION
1211
#include <stdexcept>
1312
#include <typeinfo>
1413
#include <sstream>
@@ -73,121 +72,42 @@ namespace eigenpy
7372
ARRAY_TYPE
7473
};
7574

76-
struct NumpyType
75+
struct EIGENPY_DLLEXPORT NumpyType
7776
{
7877

79-
static NumpyType & getInstance()
80-
{
81-
static NumpyType instance;
82-
return instance;
83-
}
78+
static NumpyType & getInstance();
8479

8580
operator bp::object () { return getInstance().CurrentNumpyType; }
8681

87-
static bp::object make(PyArrayObject* pyArray, bool copy = false)
88-
{ return make((PyObject*)pyArray,copy); }
82+
static bp::object make(PyArrayObject* pyArray, bool copy = false);
8983

90-
static bp::object make(PyObject* pyObj, bool copy = false)
91-
{
92-
bp::object m;
93-
if(isMatrix())
94-
m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
95-
// m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
96-
else if(isArray())
97-
m = bp::object(bp::handle<>(pyObj)); // nothing to do here
98-
99-
Py_INCREF(m.ptr());
100-
return m;
101-
}
84+
static bp::object make(PyObject* pyObj, bool copy = false);
10285

103-
static void setNumpyType(bp::object & obj)
104-
{
105-
PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
106-
if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
107-
switchToNumpyMatrix();
108-
else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
109-
switchToNumpyArray();
110-
}
86+
static void setNumpyType(bp::object & obj);
11187

112-
static void sharedMemory(const bool value)
113-
{
114-
getInstance().shared_memory = value;
115-
}
88+
static void sharedMemory(const bool value);
11689

117-
static bool sharedMemory()
118-
{
119-
return getInstance().shared_memory;
120-
}
90+
static bool sharedMemory();
12191

122-
static void switchToNumpyArray()
123-
{
124-
getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
125-
getInstance().getType() = ARRAY_TYPE;
126-
}
92+
static void switchToNumpyArray();
12793

128-
static void switchToNumpyMatrix()
129-
{
130-
getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
131-
getInstance().getType() = MATRIX_TYPE;
132-
}
94+
static void switchToNumpyMatrix();
13395

134-
static NP_TYPE & getType()
135-
{
136-
return getInstance().np_type;
137-
}
96+
static NP_TYPE & getType();
13897

139-
static bp::object getNumpyType()
140-
{
141-
return getInstance().CurrentNumpyType;
142-
}
98+
static bp::object getNumpyType();
14399

144-
static const PyTypeObject * getNumpyMatrixType()
145-
{
146-
return getInstance().NumpyMatrixType;
147-
}
100+
static const PyTypeObject * getNumpyMatrixType();
148101

149-
static const PyTypeObject * getNumpyArrayType()
150-
{
151-
return getInstance().NumpyArrayType;
152-
}
102+
static const PyTypeObject * getNumpyArrayType();
153103

154-
static bool isMatrix()
155-
{
156-
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
157-
getInstance().NumpyMatrixType);
158-
}
104+
static bool isMatrix();
159105

160-
static bool isArray()
161-
{
162-
if(getInstance().isMatrix()) return false;
163-
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
164-
getInstance().NumpyArrayType);
165-
}
106+
static bool isArray();
166107

167108
protected:
168109

169-
NumpyType()
170-
{
171-
pyModule = bp::import("numpy");
172-
173-
#if PY_MAJOR_VERSION >= 3
174-
// TODO I don't know why this Py_INCREF is necessary.
175-
// Without it, the destructor of NumpyType SEGV sometimes.
176-
Py_INCREF(pyModule.ptr());
177-
#endif
178-
179-
NumpyMatrixObject = pyModule.attr("matrix");
180-
NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
181-
NumpyArrayObject = pyModule.attr("ndarray");
182-
NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
183-
//NumpyAsMatrixObject = pyModule.attr("asmatrix");
184-
//NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());
185-
186-
CurrentNumpyType = NumpyArrayObject; // default conversion
187-
np_type = ARRAY_TYPE;
188-
189-
shared_memory = true;
190-
}
110+
NumpyType();
191111

192112
bp::object CurrentNumpyType;
193113
bp::object pyModule;

include/eigenpy/numpy.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ namespace eigenpy
3737
#if defined _WIN32 || defined __CYGWIN__
3838
namespace eigenpy
3939
{
40+
EIGENPY_DLLEXPORT bool call_PyArray_Check(PyObject *);
41+
4042
EIGENPY_DLLEXPORT PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type);
4143

4244
EIGENPY_DLLEXPORT PyObject* call_PyArray_New(PyTypeObject * py_type_ptr, int nd, npy_intp * shape, int np_type, void * data_ptr, int options);
@@ -52,6 +54,7 @@ namespace eigenpy
5254
EIGENPY_DLLEXPORT int call_PyArray_RegisterDataType(PyArray_Descr * dtype);
5355
}
5456
#else
57+
#define call_PyArray_Check(py_obj) PyArray_Check(py_obj)
5558
#define call_PyArray_SimpleNew PyArray_SimpleNew
5659
#define call_PyArray_New(py_type_ptr,nd,shape,np_type,data_ptr,options) \
5760
PyArray_New(py_type_ptr,nd,shape,np_type,NULL,data_ptr,0,options,NULL)

src/numpy-type.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2018-2020 INRIA
3+
*/
4+
5+
#include "eigenpy/numpy-type.hpp"
6+
7+
#include <patchlevel.h> // For PY_MAJOR_VERSION
8+
9+
namespace eigenpy
10+
{
11+
namespace bp = boost::python;
12+
13+
NumpyType & NumpyType::getInstance()
14+
{
15+
static NumpyType instance;
16+
return instance;
17+
}
18+
19+
bp::object NumpyType::make(PyArrayObject* pyArray, bool copy)
20+
{ return make((PyObject*)pyArray,copy); }
21+
22+
bp::object NumpyType::make(PyObject* pyObj, bool copy)
23+
{
24+
bp::object m;
25+
if(isMatrix())
26+
m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
27+
// m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
28+
else if(isArray())
29+
m = bp::object(bp::handle<>(pyObj)); // nothing to do here
30+
31+
Py_INCREF(m.ptr());
32+
return m;
33+
}
34+
35+
void NumpyType::setNumpyType(bp::object & obj)
36+
{
37+
PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
38+
if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
39+
switchToNumpyMatrix();
40+
else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
41+
switchToNumpyArray();
42+
}
43+
44+
void NumpyType::sharedMemory(const bool value)
45+
{
46+
getInstance().shared_memory = value;
47+
}
48+
49+
bool NumpyType::sharedMemory()
50+
{
51+
return getInstance().shared_memory;
52+
}
53+
54+
void NumpyType::switchToNumpyArray()
55+
{
56+
getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
57+
getInstance().getType() = ARRAY_TYPE;
58+
}
59+
60+
void NumpyType::switchToNumpyMatrix()
61+
{
62+
getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
63+
getInstance().getType() = MATRIX_TYPE;
64+
}
65+
66+
NP_TYPE & NumpyType::getType()
67+
{
68+
return getInstance().np_type;
69+
}
70+
71+
bp::object NumpyType::getNumpyType()
72+
{
73+
return getInstance().CurrentNumpyType;
74+
}
75+
76+
const PyTypeObject * NumpyType::getNumpyMatrixType()
77+
{
78+
return getInstance().NumpyMatrixType;
79+
}
80+
81+
const PyTypeObject * NumpyType::getNumpyArrayType()
82+
{
83+
return getInstance().NumpyArrayType;
84+
}
85+
86+
bool NumpyType::isMatrix()
87+
{
88+
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
89+
getInstance().NumpyMatrixType);
90+
}
91+
92+
bool NumpyType::isArray()
93+
{
94+
if(getInstance().isMatrix()) return false;
95+
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
96+
getInstance().NumpyArrayType);
97+
}
98+
99+
NumpyType::NumpyType()
100+
{
101+
pyModule = bp::import("numpy");
102+
103+
#if PY_MAJOR_VERSION >= 3
104+
// TODO I don't know why this Py_INCREF is necessary.
105+
// Without it, the destructor of NumpyType SEGV sometimes.
106+
Py_INCREF(pyModule.ptr());
107+
#endif
108+
109+
NumpyMatrixObject = pyModule.attr("matrix");
110+
NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
111+
NumpyArrayObject = pyModule.attr("ndarray");
112+
NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
113+
//NumpyAsMatrixObject = pyModule.attr("asmatrix");
114+
//NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());
115+
116+
CurrentNumpyType = NumpyArrayObject; // default conversion
117+
np_type = ARRAY_TYPE;
118+
119+
shared_memory = true;
120+
}
121+
}

src/numpy.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ namespace eigenpy
2222

2323
#if defined _WIN32 || defined __CYGWIN__
2424

25+
bool call_PyArray_Check(PyObject * py_obj)
26+
{
27+
return PyArray_Check(py_obj);
28+
}
29+
2530
PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type)
2631
{
2732
return PyArray_SimpleNew(nd,shape,np_type);

unittest/matrix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,22 @@ MatrixDerived base(const Eigen::MatrixBase<MatrixDerived> & m)
8181
return m.derived();
8282
}
8383

84+
template<typename Scalar>
85+
Eigen::Matrix<Scalar,6,6> matrix6(const Scalar & value)
86+
{
87+
typedef Eigen::Matrix<Scalar,6,6> ReturnType;
88+
return ReturnType::Constant(value);
89+
}
90+
8491
BOOST_PYTHON_MODULE(matrix)
8592
{
8693
using namespace Eigen;
8794
namespace bp = boost::python;
8895
eigenpy::enableEigenPy();
8996

97+
typedef Eigen::Matrix<double,6,6> Matrix6;
98+
eigenpy::enableEigenPySpecific<Matrix6>();
99+
90100
Eigen::MatrixXd (*naturalsXX)(int,int,bool) = naturals;
91101
Eigen::VectorXd (*naturalsX)(int,bool) = naturals;
92102
Eigen::Matrix3d (*naturals33)(bool) = naturals;
@@ -108,4 +118,6 @@ BOOST_PYTHON_MODULE(matrix)
108118

109119
bp::def("base", base<VectorXd>);
110120
bp::def("base", base<MatrixXd>);
121+
122+
bp::def("matrix6", matrix6<double>);
111123
}

unittest/python/test_matrix.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,7 @@
126126
vec1x1 = eigenpy.vector1x1(value)
127127
assert(vec1x1.size == 1)
128128
assert(vec1x1[0] == value)
129+
130+
# test registration of matrix6
131+
mat6 = eigenpy.matrix6(0.)
132+
assert(mat6.size == 36)

0 commit comments

Comments
 (0)