From 0991e90375606254087f7bffe0dd15dd910ec62b Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 11 Nov 2018 17:24:32 +0100 Subject: [PATCH] fix py::cast Pybind11 provides a cast operator between opaque void* pointers on the C++ side and capsules on the Python side. The py::cast 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. --- include/pybind11/cast.h | 3 ++- tests/test_builtin_casters.cpp | 7 +++++++ tests/test_builtin_casters.py | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 2dec23cb3..80abb2b93 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1611,7 +1611,8 @@ template using move_never = none_of, move_if_unrefer // everything else returns a reference/pointer to a local variable. template using cast_is_temporary_value_reference = bool_constant< (std::is_reference::value || std::is_pointer::value) && - !std::is_base_of>::value + !std::is_base_of>::value && + !std::is_same, void>::value >; // When a value returned from a C++ function is being cast back to Python, we almost always want to diff --git a/tests/test_builtin_casters.cpp b/tests/test_builtin_casters.cpp index 450813403..e026127f8 100644 --- a/tests/test_builtin_casters.cpp +++ b/tests/test_builtin_casters.cpp @@ -160,4 +160,11 @@ TEST_SUBMODULE(builtin_casters, m) { m.def("int_cast", []() {return (int) 42;}); m.def("long_cast", []() {return (long) 42;}); 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(o) == v; + }); } diff --git a/tests/test_builtin_casters.py b/tests/test_builtin_casters.py index 01d0437b5..73cc465f5 100644 --- a/tests/test_builtin_casters.py +++ b/tests/test_builtin_casters.py @@ -336,3 +336,7 @@ def test_int_long(): assert isinstance(m.int_cast(), int) assert isinstance(m.long_cast(), int) assert isinstance(m.longlong_cast(), must_be_long) + + +def test_void_caster_2(): + assert m.test_void_caster()