fix py::cast<void *>

Pybind11 provides a cast operator between opaque void* pointers on the
C++ side and capsules on the Python side. The py::cast<void *>
expression was not aware of this possibility and incorrectly triggered a
compile-time assertion ("Unable to cast type to reference: value is
local to type caster") that is now fixed.
This commit is contained in:
Wenzel Jakob 2018-11-11 17:24:32 +01:00
parent e2eca4f8f8
commit 0991e90375
3 changed files with 13 additions and 1 deletions

View File

@ -1611,7 +1611,8 @@ template <typename T> using move_never = none_of<move_always<T>, move_if_unrefer
// everything else returns a reference/pointer to a local variable. // everything else returns a reference/pointer to a local variable.
template <typename type> using cast_is_temporary_value_reference = bool_constant< template <typename type> using cast_is_temporary_value_reference = bool_constant<
(std::is_reference<type>::value || std::is_pointer<type>::value) && (std::is_reference<type>::value || std::is_pointer<type>::value) &&
!std::is_base_of<type_caster_generic, make_caster<type>>::value !std::is_base_of<type_caster_generic, make_caster<type>>::value &&
!std::is_same<intrinsic_t<type>, void>::value
>; >;
// When a value returned from a C++ function is being cast back to Python, we almost always want to // When a value returned from a C++ function is being cast back to Python, we almost always want to

View File

@ -160,4 +160,11 @@ TEST_SUBMODULE(builtin_casters, m) {
m.def("int_cast", []() {return (int) 42;}); m.def("int_cast", []() {return (int) 42;});
m.def("long_cast", []() {return (long) 42;}); m.def("long_cast", []() {return (long) 42;});
m.def("longlong_cast", []() {return ULLONG_MAX;}); m.def("longlong_cast", []() {return ULLONG_MAX;});
/// test void* cast operator
m.def("test_void_caster", []() -> bool {
void *v = (void *) 0xabcd;
py::object o = py::cast(v);
return py::cast<void *>(o) == v;
});
} }

View File

@ -336,3 +336,7 @@ def test_int_long():
assert isinstance(m.int_cast(), int) assert isinstance(m.int_cast(), int)
assert isinstance(m.long_cast(), int) assert isinstance(m.long_cast(), int)
assert isinstance(m.longlong_cast(), must_be_long) assert isinstance(m.longlong_cast(), must_be_long)
def test_void_caster_2():
assert m.test_void_caster()