diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index c8a5014e3..a5aff662a 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -1016,8 +1016,8 @@ public: PYBIND11_DEPRECATED("Use reinterpret_borrow() or reinterpret_steal()") capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed_t{}) : object(ptr, stolen_t{})) { } - explicit capsule(const void *value) - : object(PyCapsule_New(const_cast(value), nullptr, nullptr), stolen_t{}) { + explicit capsule(const void *value, const char *name = nullptr, void (*destructor)(PyObject *) = nullptr) + : object(PyCapsule_New(const_cast(value), name, destructor), stolen_t{}) { if (!m_ptr) pybind11_fail("Could not allocate capsule object!"); } @@ -1054,10 +1054,13 @@ public: } template operator T *() const { - T * result = static_cast(PyCapsule_GetPointer(m_ptr, nullptr)); + auto name = this->name(); + T * result = static_cast(PyCapsule_GetPointer(m_ptr, name)); if (!result) pybind11_fail("Unable to extract capsule contents!"); return result; } + + const char *name() const { return PyCapsule_GetName(m_ptr); } }; class tuple : public object { diff --git a/tests/test_python_types.cpp b/tests/test_python_types.cpp index 0d7ea502b..a3ed2895b 100644 --- a/tests/test_python_types.cpp +++ b/tests/test_python_types.cpp @@ -573,6 +573,22 @@ test_initializer python_types([](py::module &m) { } ); + m.def("return_capsule_with_name_and_destructor_3", + []() { + py::print("creating capsule"); + auto capsule=py::capsule((void *) 1234, "pointer type description", + [](PyObject *ptr) { + if (ptr) { + py::print("destructing capsule"); + } + }); + auto name = capsule.name(); + void *contents = capsule; + py::print("created capsule with name --{}-- and contents {}"_s.format(name,(size_t) contents)); + return capsule; + } + ); + m.def("load_nullptr_t", [](std::nullptr_t) {}); // not useful, but it should still compile m.def("cast_nullptr_t", []() { return std::nullptr_t{}; }); diff --git a/tests/test_python_types.py b/tests/test_python_types.py index 08bb3abe9..ecd317e20 100644 --- a/tests/test_python_types.py +++ b/tests/test_python_types.py @@ -603,10 +603,19 @@ def test_capsule_with_destructor(capture): destructing capsule: 1234 """ + with capture: + a = m.return_capsule_with_name_and_destructor_3() + del a + pytest.gc_collect() + assert capture.unordered == """ + created capsule with name --pointer type description-- and contents 1234 + creating capsule + destructing capsule + """ + def test_void_caster(): import pybind11_tests as m - assert m.load_nullptr_t(None) is None assert m.cast_nullptr_t() is None