@@ -173,7 +173,8 @@ Module Destructors
173
173
174
174
pybind11 does not provide an explicit mechanism to invoke cleanup code at
175
175
module destruction time. In rare cases where such functionality is required, it
176
- is possible to emulate it using Python capsules with a destruction callback.
176
+ is possible to emulate it using Python capsules or weak references with a
177
+ destruction callback.
177
178
178
179
.. code-block :: cpp
179
180
@@ -183,6 +184,39 @@ is possible to emulate it using Python capsules with a destruction callback.
183
184
184
185
m.add_object("_cleanup", py::capsule(cleanup_callback));
185
186
187
+ This approach has the potential downside that instances of classes exposed
188
+ within the module may still be alive when the cleanup callback is invoked
189
+ (whether this is acceptable will generally depend on the application).
190
+
191
+ Alternatively, the capsule may also be stashed within a type object, which
192
+ ensures that it not called before all instances of that type have been
193
+ collected:
194
+
195
+ .. code-block :: cpp
196
+
197
+ auto cleanup_callback = []() { /* ... */ };
198
+ m.attr("BaseClass").attr("_cleanup") = py::capsule(cleanup_callback);
199
+
200
+ Both approaches also expose a potentially dangerous ``_cleanup `` attribute in
201
+ Python, which may be undesirable from an API standpoint (a premature explicit
202
+ call from Python might lead to undefined behavior). Yet another approach that
203
+ avoids this issue involves weak reference with a cleanup callback:
204
+
205
+ .. code-block :: cpp
206
+
207
+ // Register a callback function that is invoked when the BaseClass object is colelcted
208
+ py::cpp_function cleanup_callback(
209
+ [](py::handle weakref) {
210
+ // perform cleanup here -- this function is called with the GIL held
211
+
212
+ weakref.dec_ref(); // release weak reference
213
+ }
214
+ );
215
+
216
+ // Create a weak reference with a cleanup callback and initially leak it
217
+ (void) py::weakref(m.attr("BaseClass"), cleanup_callback).release();
218
+
219
+
186
220
Generating documentation using Sphinx
187
221
=====================================
188
222
0 commit comments