mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
Fix type caster for heap reference types
Need to use the intrinsic type, not the raw type. Fixes #392.
This commit is contained in:
parent
8706fb9085
commit
56f717756b
@ -259,24 +259,25 @@ using cast_op_type = typename std::conditional<std::is_pointer<typename std::rem
|
|||||||
|
|
||||||
/// Generic type caster for objects stored on the heap
|
/// Generic type caster for objects stored on the heap
|
||||||
template <typename type> class type_caster_base : public type_caster_generic {
|
template <typename type> class type_caster_base : public type_caster_generic {
|
||||||
|
using itype = intrinsic_t<type>;
|
||||||
public:
|
public:
|
||||||
static PYBIND11_DESCR name() { return type_descr(_<type>()); }
|
static PYBIND11_DESCR name() { return type_descr(_<type>()); }
|
||||||
|
|
||||||
type_caster_base() : type_caster_generic(typeid(type)) { }
|
type_caster_base() : type_caster_generic(typeid(type)) { }
|
||||||
|
|
||||||
static handle cast(const type &src, return_value_policy policy, handle parent) {
|
static handle cast(const itype &src, return_value_policy policy, handle parent) {
|
||||||
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
||||||
policy = return_value_policy::copy;
|
policy = return_value_policy::copy;
|
||||||
return cast(&src, policy, parent);
|
return cast(&src, policy, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static handle cast(type &&src, return_value_policy policy, handle parent) {
|
static handle cast(itype &&src, return_value_policy policy, handle parent) {
|
||||||
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
||||||
policy = return_value_policy::move;
|
policy = return_value_policy::move;
|
||||||
return cast(&src, policy, parent);
|
return cast(&src, policy, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static handle cast(const type *src, return_value_policy policy, handle parent) {
|
static handle cast(const itype *src, return_value_policy policy, handle parent) {
|
||||||
return type_caster_generic::cast(
|
return type_caster_generic::cast(
|
||||||
src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type),
|
src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type),
|
||||||
make_copy_constructor(src), make_move_constructor(src));
|
make_copy_constructor(src), make_move_constructor(src));
|
||||||
@ -284,8 +285,8 @@ public:
|
|||||||
|
|
||||||
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
|
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
|
||||||
|
|
||||||
operator type*() { return (type *) value; }
|
operator itype*() { return (type *) value; }
|
||||||
operator type&() { if (!value) throw reference_cast_error(); return *((type *) value); }
|
operator itype&() { if (!value) throw reference_cast_error(); return *((itype *) value); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef void *(*Constructor)(const void *stream);
|
typedef void *(*Constructor)(const void *stream);
|
||||||
|
@ -191,6 +191,35 @@ void init_issues(py::module &m) {
|
|||||||
py::class_<MoveIssue2>(m2, "MoveIssue2").def(py::init<int>()).def_readwrite("value", &MoveIssue2::v);
|
py::class_<MoveIssue2>(m2, "MoveIssue2").def(py::init<int>()).def_readwrite("value", &MoveIssue2::v);
|
||||||
m2.def("get_moveissue1", [](int i) -> MoveIssue1 * { return new MoveIssue1(i); }, py::return_value_policy::move);
|
m2.def("get_moveissue1", [](int i) -> MoveIssue1 * { return new MoveIssue1(i); }, py::return_value_policy::move);
|
||||||
m2.def("get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
|
m2.def("get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
|
||||||
|
|
||||||
|
// Issue 392: overridding reference-returning functions
|
||||||
|
class OverrideTest {
|
||||||
|
public:
|
||||||
|
struct A { int value = 99; };
|
||||||
|
int v;
|
||||||
|
A a;
|
||||||
|
explicit OverrideTest(int v) : v{v} {}
|
||||||
|
virtual int int_value() { return v; }
|
||||||
|
virtual int &int_ref() { return v; }
|
||||||
|
virtual A A_value() { return a; }
|
||||||
|
virtual A &A_ref() { return a; }
|
||||||
|
};
|
||||||
|
class PyOverrideTest : public OverrideTest {
|
||||||
|
public:
|
||||||
|
using OverrideTest::OverrideTest;
|
||||||
|
int int_value() override { PYBIND11_OVERLOAD(int, OverrideTest, int_value); }
|
||||||
|
int &int_ref() override { PYBIND11_OVERLOAD(int &, OverrideTest, int_ref); }
|
||||||
|
A A_value() override { PYBIND11_OVERLOAD(A, OverrideTest, A_value); }
|
||||||
|
A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); }
|
||||||
|
};
|
||||||
|
py::class_<OverrideTest::A>(m2, "OverrideTest_A")
|
||||||
|
.def_readwrite("value", &OverrideTest::A::value);
|
||||||
|
py::class_<OverrideTest, PyOverrideTest>(m2, "OverrideTest")
|
||||||
|
.def(py::init<int>())
|
||||||
|
.def("int_value", &OverrideTest::int_value)
|
||||||
|
.def("int_ref", &OverrideTest::int_ref)
|
||||||
|
.def("A_value", &OverrideTest::A_value)
|
||||||
|
.def("A_ref", &OverrideTest::A_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MSVC workaround: trying to use a lambda here crashes MSCV
|
// MSVC workaround: trying to use a lambda here crashes MSCV
|
||||||
|
@ -166,3 +166,17 @@ def test_move_fallback():
|
|||||||
assert m2.value == 2
|
assert m2.value == 2
|
||||||
m1 = get_moveissue1(1)
|
m1 = get_moveissue1(1)
|
||||||
assert m1.value == 1
|
assert m1.value == 1
|
||||||
|
|
||||||
|
def test_override_ref():
|
||||||
|
from pybind11_tests.issues import OverrideTest
|
||||||
|
o = OverrideTest(42)
|
||||||
|
|
||||||
|
i = o.int_ref()
|
||||||
|
assert o.int_value() == 42
|
||||||
|
assert o.int_ref() == 42
|
||||||
|
|
||||||
|
assert o.A_value().value == 99
|
||||||
|
a = o.A_ref()
|
||||||
|
assert a.value == 99
|
||||||
|
a.value = 7
|
||||||
|
assert a.value == 7
|
||||||
|
Loading…
Reference in New Issue
Block a user