Skip to content

Commit 0c99402

Browse files
committed
added destructor-only version of capsule & tests
1 parent f35fdc0 commit 0c99402

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

include/pybind11/pytypes.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,16 @@ class capsule : public object {
10321032
pybind11_fail("Could not set capsule context!");
10331033
}
10341034

1035+
capsule(void (*destructor)()) {
1036+
m_ptr = PyCapsule_New(reinterpret_cast<void *>(destructor), nullptr, [](PyObject *o) {
1037+
auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, nullptr));
1038+
destructor();
1039+
});
1040+
1041+
if (!m_ptr)
1042+
pybind11_fail("Could not allocate capsule object!");
1043+
}
1044+
10351045
template <typename T> operator T *() const {
10361046
T * result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, nullptr));
10371047
if (!result) pybind11_fail("Unable to extract capsule contents!");

tests/test_python_types.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,24 @@ test_initializer python_types([](py::module &m) {
470470
m.def("return_none_bool", []() -> bool * { return nullptr; });
471471
m.def("return_none_int", []() -> int * { return nullptr; });
472472
m.def("return_none_float", []() -> float * { return nullptr; });
473+
474+
m.def("return_capsule_with_destructor",
475+
[]() {
476+
py::print("creating capsule");
477+
return py::capsule([]() {
478+
py::print("destructing capsule");
479+
});
480+
}
481+
);
482+
483+
m.def("return_capsule_with_destructor_2",
484+
[]() {
485+
py::print("creating capsule");
486+
return py::capsule((void *) 1234, [](void *ptr) {
487+
py::print("destructing capsule: {}"_s.format((size_t) ptr));
488+
});
489+
}
490+
);
473491
});
474492

475493
#if defined(_MSC_VER)

tests/test_python_types.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,3 +512,22 @@ def test_builtins_cast_return_none():
512512
assert m.return_none_bool() is None
513513
assert m.return_none_int() is None
514514
assert m.return_none_float() is None
515+
516+
def test_capsule_with_destructor(capture):
517+
import pybind11_tests as m
518+
with capture:
519+
a = m.return_capsule_with_destructor()
520+
del a
521+
assert capture.unordered == """
522+
creating capsule
523+
destructing capsule
524+
"""
525+
526+
with capture:
527+
a = m.return_capsule_with_destructor_2()
528+
del a
529+
print(capture)
530+
assert capture.unordered == """
531+
creating capsule
532+
destructing capsule: 1234
533+
"""

0 commit comments

Comments
 (0)