-
Notifications
You must be signed in to change notification settings - Fork 46
Open
Description
Consider the following example:
template <typename MatType>
const Eigen::Ref<const MatType> asConstRef(Eigen::Ref<const MatType> mat) {
doSomething(mat);
return Eigen::Ref<const MatType>(mat);
}
// in BOOST_PYTHON_MODULE
bp::def("asRef", asConstRef<Eigen::MatrixXd>); // notice this is the *ColMajor* matrix
//
This will work:
A = np.eye(2, order="F")
aref = asConstRef(A)
assert np.array_equal(A, aref)
assert not aref.flags.owndata
assert not aref.flags.writeable
This will not:
A = np.eye(2, order="C") # "C" is the numpy default
aref = asConstRef(A)
assert np.array_equal(A, aref) # fails
assert not aref.flags.owndata # ok
assert not aref.flags.writeable # ok
After discussing with @jcarpent we came to the conclusion that the return statement in C++, due to how EigenAllocator<Eigen::Ref<cv MatType>, ...>
is wired up, returns something pointing to the wrong memory - actually, to temporary C++ memory created by EigenAllocator and of which an Eigen::Ref is given to asConstRef
. This temporary memory is a (col-major) Eigen::MatrixXd
created to host a copy of the (row-major) Numpy input, and destroyed in the destructor of the rvalue_from_python_data
handler before the function returns. What is inside the returned aref
view is random memory.
This was discovered while working in PR #325.
Two possibilities:
- redefine the Eigen::Ref types to have dynamic stride as to allow mapping from column major to row major; rework the EigenAllocator
- disallow the above.
Metadata
Metadata
Assignees
Labels
No labels