Skip to content

Commit

Permalink
Merge pull request #153 from jcarpent/devel
Browse files Browse the repository at this point in the history
Fix potential bug introduced in 2.0.0
  • Loading branch information
jcarpent authored Jan 31, 2020
2 parents 27e7995 + 3e93257 commit dffd691
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 119 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ SET(${PROJECT_NAME}_HEADERS
include/eigenpy/geometry.hpp
include/eigenpy/geometry-conversion.hpp
include/eigenpy/memory.hpp
include/eigenpy/numpy-type.hpp
include/eigenpy/registration.hpp
include/eigenpy/angle-axis.hpp
include/eigenpy/quaternion.hpp
Expand Down
2 changes: 1 addition & 1 deletion cmake
Submodule cmake updated 1 files
+3 −3 python.cmake
119 changes: 1 addition & 118 deletions include/eigenpy/details.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <iostream>

#include "eigenpy/eigenpy.hpp"
#include "eigenpy/numpy-type.hpp"
#include "eigenpy/registration.hpp"
#include "eigenpy/map.hpp"
#include "eigenpy/exception.hpp"
Expand Down Expand Up @@ -64,124 +65,6 @@ namespace eigenpy

namespace bp = boost::python;

enum NP_TYPE
{
MATRIX_TYPE,
ARRAY_TYPE
};

struct NumpyType
{

static NumpyType & getInstance()
{
static NumpyType instance;
return instance;
}

operator bp::object () { return CurrentNumpyType; }

bp::object make(PyArrayObject* pyArray, bool copy = false)
{ return make((PyObject*)pyArray,copy); }

bp::object make(PyObject* pyObj, bool copy = false)
{
bp::object m;
if(PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(CurrentNumpyType.ptr()),NumpyMatrixType))
m = NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
// m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
else if(PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(CurrentNumpyType.ptr()),NumpyArrayType))
m = bp::object(bp::handle<>(pyObj)); // nothing to do here

Py_INCREF(m.ptr());
return m;
}

static void setNumpyType(bp::object & obj)
{
PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
switchToNumpyMatrix();
else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
switchToNumpyArray();
}

static void switchToNumpyArray()
{
getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
getType() = ARRAY_TYPE;
}

static void switchToNumpyMatrix()
{
getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
getType() = MATRIX_TYPE;
}

static NP_TYPE & getType()
{
static NP_TYPE np_type;
return np_type;
}

static bp::object getNumpyType()
{
return getInstance().CurrentNumpyType;
}

static const PyTypeObject * getNumpyMatrixType()
{
return getInstance().NumpyMatrixType;
}

static const PyTypeObject * getNumpyArrayType()
{
return getInstance().NumpyArrayType;
}

static bool isMatrix()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyMatrixType);
}

static bool isArray()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyArrayType);
}

protected:
NumpyType()
{
pyModule = bp::import("numpy");
#if PY_MAJOR_VERSION >= 3
// TODO I don't know why this Py_INCREF is necessary.
// Without it, the destructor of NumpyType SEGV sometimes.
Py_INCREF(pyModule.ptr());
#endif

NumpyMatrixObject = pyModule.attr("matrix");
NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
NumpyArrayObject = pyModule.attr("ndarray");
NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
//NumpyAsMatrixObject = pyModule.attr("asmatrix");
//NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());

CurrentNumpyType = NumpyArrayObject; // default conversion
getType() = ARRAY_TYPE;
}

bp::object CurrentNumpyType;
bp::object pyModule;

// Numpy types
bp::object NumpyMatrixObject; PyTypeObject * NumpyMatrixType;
//bp::object NumpyAsMatrixObject; PyTypeObject * NumpyAsMatrixType;
bp::object NumpyArrayObject; PyTypeObject * NumpyArrayType;

};

template<typename MatType, bool IsVectorAtCompileTime = MatType::IsVectorAtCompileTime>
struct initEigenObject
{
Expand Down
5 changes: 5 additions & 0 deletions include/eigenpy/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* Copyright 2018-2020, INRIA
*/

#ifndef __eigenpy_map_hpp__
#define __eigenpy_map_hpp__

#include "eigenpy/fwd.hpp"
#include <numpy/arrayobject.h>
#include "eigenpy/exception.hpp"
Expand Down Expand Up @@ -126,3 +129,5 @@ namespace eigenpy
}

} // namespace eigenpy

#endif // define __eigenpy_map_hpp__
138 changes: 138 additions & 0 deletions include/eigenpy/numpy-type.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright 2018-2020, INRIA
*/

#ifndef __eigenpy_numpy_type_hpp__
#define __eigenpy_numpy_type_hpp__

#include "eigenpy/fwd.hpp"

#include <iostream>
#include <patchlevel.h> // For PY_MAJOR_VERSION

namespace eigenpy
{
namespace bp = boost::python;

enum NP_TYPE
{
MATRIX_TYPE,
ARRAY_TYPE
};

struct NumpyType
{

static NumpyType & getInstance()
{
static NumpyType instance;
return instance;
}

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

static bp::object make(PyArrayObject* pyArray, bool copy = false)
{ return make((PyObject*)pyArray,copy); }

static bp::object make(PyObject* pyObj, bool copy = false)
{
bp::object m;
if(isMatrix())
m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
// m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
else if(isArray())
m = bp::object(bp::handle<>(pyObj)); // nothing to do here

Py_INCREF(m.ptr());
return m;
}

static void setNumpyType(bp::object & obj)
{
PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
switchToNumpyMatrix();
else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
switchToNumpyArray();
}

static void switchToNumpyArray()
{
getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
getInstance().getType() = ARRAY_TYPE;
}

static void switchToNumpyMatrix()
{
getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
getInstance().getType() = MATRIX_TYPE;
}

static NP_TYPE & getType()
{
return getInstance().np_type;
}

static bp::object getNumpyType()
{
return getInstance().CurrentNumpyType;
}

static const PyTypeObject * getNumpyMatrixType()
{
return getInstance().NumpyMatrixType;
}

static const PyTypeObject * getNumpyArrayType()
{
return getInstance().NumpyArrayType;
}

static bool isMatrix()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyMatrixType);
}

static bool isArray()
{
if(getInstance().isMatrix()) return false;
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyArrayType);
}

protected:
NumpyType()
{
pyModule = bp::import("numpy");
#if PY_MAJOR_VERSION >= 3
// TODO I don't know why this Py_INCREF is necessary.
// Without it, the destructor of NumpyType SEGV sometimes.
Py_INCREF(pyModule.ptr());
#endif

NumpyMatrixObject = pyModule.attr("matrix");
NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
NumpyArrayObject = pyModule.attr("ndarray");
NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
//NumpyAsMatrixObject = pyModule.attr("asmatrix");
//NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());

CurrentNumpyType = NumpyArrayObject; // default conversion
np_type = ARRAY_TYPE;
}

bp::object CurrentNumpyType;
bp::object pyModule;

// Numpy types
bp::object NumpyMatrixObject; PyTypeObject * NumpyMatrixType;
//bp::object NumpyAsMatrixObject; PyTypeObject * NumpyAsMatrixType;
bp::object NumpyArrayObject; PyTypeObject * NumpyArrayType;

NP_TYPE np_type;
};

}

#endif // ifndef __eigenpy_numpy_type_hpp__
1 change: 1 addition & 0 deletions unittest/python/test_dimensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

quat = eigenpy.Quaternion()
# By default, we convert as numpy.matrix
eigenpy.switchToNumpyMatrix()
coeffs_vector = quat.coeffs()
assert len(coeffs_vector.shape) == 2

Expand Down

0 comments on commit dffd691

Please sign in to comment.