mirror of
https://github.com/RYDE-WORK/pybind11.git
synced 2026-02-03 22:14:33 +08:00
Fix indirect loading of Eigen::Ref
Put the caster's temporary array on life support to ensure correct lifetime when it's being used as a subcaster.
This commit is contained in:
parent
af2dda38ef
commit
30f6c3b36e
@ -462,6 +462,7 @@ public:
|
|||||||
if (!fits || !fits.template stride_compatible<props>())
|
if (!fits || !fits.template stride_compatible<props>())
|
||||||
return false;
|
return false;
|
||||||
copy_or_ref = std::move(copy);
|
copy_or_ref = std::move(copy);
|
||||||
|
loader_life_support::add_patient(copy_or_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref.reset();
|
ref.reset();
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "pybind11_tests.h"
|
#include "pybind11_tests.h"
|
||||||
#include "constructor_stats.h"
|
#include "constructor_stats.h"
|
||||||
#include <pybind11/eigen.h>
|
#include <pybind11/eigen.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
#include <Eigen/Cholesky>
|
#include <Eigen/Cholesky>
|
||||||
|
|
||||||
using MatrixXdR = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
|
using MatrixXdR = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
|
||||||
@ -298,4 +299,17 @@ test_initializer eigen([](py::module &m) {
|
|||||||
.def(py::init<>())
|
.def(py::init<>())
|
||||||
.def_readonly("a", &CustomOperatorNew::a)
|
.def_readonly("a", &CustomOperatorNew::a)
|
||||||
.def_readonly("b", &CustomOperatorNew::b);
|
.def_readonly("b", &CustomOperatorNew::b);
|
||||||
|
|
||||||
|
// test_eigen_ref_life_support
|
||||||
|
// In case of a failure (the caster's temp array does not live long enough), creating
|
||||||
|
// a new array (np.ones(10)) increases the chances that the temp array will be garbage
|
||||||
|
// collected and/or that its memory will be overridden with different values.
|
||||||
|
m.def("get_elem_direct", [](Eigen::Ref<const Eigen::VectorXd> v) {
|
||||||
|
py::module::import("numpy").attr("ones")(10);
|
||||||
|
return v(5);
|
||||||
|
});
|
||||||
|
m.def("get_elem_indirect", [](std::vector<Eigen::Ref<const Eigen::VectorXd>> v) {
|
||||||
|
py::module::import("numpy").attr("ones")(10);
|
||||||
|
return v[0](5);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -602,6 +602,21 @@ def test_nocopy_wrapper():
|
|||||||
', flags.c_contiguous' in str(excinfo.value))
|
', flags.c_contiguous' in str(excinfo.value))
|
||||||
|
|
||||||
|
|
||||||
|
def test_eigen_ref_life_support():
|
||||||
|
"""Ensure the lifetime of temporary arrays created by the `Ref` caster
|
||||||
|
|
||||||
|
The `Ref` caster sometimes creates a copy which needs to stay alive. This needs to
|
||||||
|
happen both for directs casts (just the array) or indirectly (e.g. list of arrays).
|
||||||
|
"""
|
||||||
|
from pybind11_tests import get_elem_direct, get_elem_indirect
|
||||||
|
|
||||||
|
a = np.full(shape=10, fill_value=8, dtype=np.int8)
|
||||||
|
assert get_elem_direct(a) == 8
|
||||||
|
|
||||||
|
list_of_a = [a]
|
||||||
|
assert get_elem_indirect(list_of_a) == 8
|
||||||
|
|
||||||
|
|
||||||
def test_special_matrix_objects():
|
def test_special_matrix_objects():
|
||||||
from pybind11_tests import incr_diag, symmetric_upper, symmetric_lower
|
from pybind11_tests import incr_diag, symmetric_upper, symmetric_lower
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user