From 5f317e60bd17f0c226bcac40ed10b26c3b68dcc0 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sat, 26 Aug 2017 00:35:05 +0200 Subject: [PATCH] extended module destructor documentation (#1031) --- docs/advanced/misc.rst | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/advanced/misc.rst b/docs/advanced/misc.rst index 6d8cfc9b8..87481ba32 100644 --- a/docs/advanced/misc.rst +++ b/docs/advanced/misc.rst @@ -173,7 +173,8 @@ Module Destructors pybind11 does not provide an explicit mechanism to invoke cleanup code at module destruction time. In rare cases where such functionality is required, it -is possible to emulate it using Python capsules with a destruction callback. +is possible to emulate it using Python capsules or weak references with a +destruction callback. .. code-block:: cpp @@ -183,6 +184,39 @@ is possible to emulate it using Python capsules with a destruction callback. m.add_object("_cleanup", py::capsule(cleanup_callback)); +This approach has the potential downside that instances of classes exposed +within the module may still be alive when the cleanup callback is invoked +(whether this is acceptable will generally depend on the application). + +Alternatively, the capsule may also be stashed within a type object, which +ensures that it not called before all instances of that type have been +collected: + +.. code-block:: cpp + + auto cleanup_callback = []() { /* ... */ }; + m.attr("BaseClass").attr("_cleanup") = py::capsule(cleanup_callback); + +Both approaches also expose a potentially dangerous ``_cleanup`` attribute in +Python, which may be undesirable from an API standpoint (a premature explicit +call from Python might lead to undefined behavior). Yet another approach that +avoids this issue involves weak reference with a cleanup callback: + +.. code-block:: cpp + + // Register a callback function that is invoked when the BaseClass object is colelcted + py::cpp_function cleanup_callback( + [](py::handle weakref) { + // perform cleanup here -- this function is called with the GIL held + + weakref.dec_ref(); // release weak reference + } + ); + + // Create a weak reference with a cleanup callback and initially leak it + (void) py::weakref(m.attr("BaseClass"), cleanup_callback).release(); + + Generating documentation using Sphinx =====================================