@@ -3,66 +3,52 @@ Smart pointers & ``py::class_``
33
44The binding generator for classes, ``py::class_ ``, can be passed a template
55type that denotes a special *holder * type that is used to manage references to
6- the object. If no such holder type template argument is given, the default for
6+ the object. If no such holder type template argument is given, the default for
77a type ``T `` is ``std::unique_ptr<T> ``.
88
9+ .. note ::
10+
11+ A ``py::class_ `` for a given C++ type ``T `` — and all its derived types —
12+ can only use a single holder type.
13+
14+
15+ .. _smart_holder :
16+
917``py::smart_holder ``
1018====================
1119
1220Starting with pybind11v3, ``py::smart_holder `` is built into pybind11. It is
13- the recommended ``py::class_ `` holder for all situations, but it is **not **
14- the default holder, and there is no intent to make it the default holder in
15- the future, based on the assumption that this would cause more disruption
16- than it is worth.
17-
18- It is extremely easy to change existing pybind11 client code to use the safer
19- and more versatile ``py::smart_holder ``. For a given C++ type ``T ``, simply
20- change
21+ the recommended ``py::class_ `` holder for most situations, but it is **not **
22+ the default holder, and there are no plans to make it the default holder in
23+ the future. This is based on the assumption that such a change would cause
24+ more disruption than it is worth, especially because it is extremely easy
25+ to use the safer and more versatile ``py::smart_holder ``. For a given C++
26+ type ``T ``, simply change
2127
2228* ``py::class_<T> `` to
23- * ``py::classh<T> ``
29+
30+ * ``py::classh<T> ``.
2431
2532.. note ::
2633
27- ``py::classh<T> `` is simply a shortcut for ``py::class_<T, py::smart_holder> ``.
34+ ``py::classh<T> `` is a shortcut for ``py::class_<T, py::smart_holder> ``.
2835
29- The ``py::classh<T> `` functionality includes
36+ The ``py::classh<T> `` functionality includes the following:
3037
31- * support for **two-way ** Python/C++ conversions for both
38+ * Support for **two-way ** Python/C++ conversions for both
3239 ``std::unique_ptr<T> `` and ``std::shared_ptr<T> `` **simultaneously **.
33- — In contrast, ``py::class_<T> `` only supports one-way C++-to-Python
34- conversions for ``std::unique_ptr<T> ``, or alternatively two-way
35- Python/C++ conversions for ``std::shared_ptr<T> ``, which then excludes
36- the one-way C++-to-Python ``std::unique_ptr<T> `` conversions (this manifests
37- itself through undefined runtime behavior, often a segmentation fault
38- or double free).
39-
40- * passing a Python object back to C++ via ``std::unique_ptr<T> ``, safely
40+
41+ * Passing a Python object back to C++ via ``std::unique_ptr<T> ``, safely
4142 **disowning ** the Python object.
4243
43- * safely passing `"trampoline"
44- <https://pybind11.readthedocs.io/en/stable/advanced/classes.html#overriding-virtual-functions-in-python> `_
45- objects (objects with C++ virtual function overrides implemented in
46- Python) via ``std::unique_ptr<T> `` or ``std::shared_ptr<T> `` back to C++:
44+ * Safely passing "trampoline" objects (objects with C++ virtual function
45+ overrides implemented in Python, see :ref: `overriding_virtuals `) via
46+ ``std::unique_ptr<T> `` or ``std::shared_ptr<T> `` back to C++:
4747 associated Python objects are automatically kept alive for the lifetime
4848 of the smart-pointer.
4949
50- TODO(rwgk): Move to classes.rst
51-
52- A pybind11 `"trampoline"
53- <https://pybind11.readthedocs.io/en/stable/advanced/classes.html#overriding-virtual-functions-in-python> `_
54- is a C++ helper class with virtual function overrides that transparently
55- call back from C++ into Python. To enable safely passing a ``std::unique_ptr ``
56- to a trampoline object between Python and C++, the trampoline class must
57- inherit from ``py::trampoline_self_life_support ``, for example:
58-
59- .. code-block :: cpp
60-
61- class PyAnimal : public Animal, public py::trampoline_self_life_support {
62- ...
63- };
64-
65- A fairly minimal but complete example is :file: `tests/test_class_sh_trampoline_unique_ptr.cpp `.
50+ * Full support for ``std::enable_shared_from_this `` (`cppreference
51+ <http://en.cppreference.com/w/cpp/memory/enable_shared_from_this> `_).
6652
6753
6854``std::unique_ptr ``
@@ -71,7 +57,7 @@ A fairly minimal but complete example is :file:`tests/test_class_sh_trampoline_u
7157This is the default ``py::class_ `` holder and works as expected in most
7258situations. However, note that the handling of base-and-derived classes
7359involves a ``reinterpret_cast `` that has strictly speaking undefined
74- behavior. Also note that the ``std::unique_ptr `` holder only support passing
60+ behavior. Also note that the ``std::unique_ptr `` holder only supports passing
7561a ``std::unique_ptr `` from C++ to Python, but not the other way around. For
7662example, this code will work as expected when using ``py::class_<Example> ``:
7763
@@ -83,7 +69,7 @@ example, this code will work as expected when using ``py::class_<Example>``:
8369
8470 m.def("create_example", &create_example);
8571
86- However, this will fail with ``py::class_<Example> `` (but work with
72+ However, this will fail with ``py::class_<Example> `` (but works with
8773``py::classh<Example> ``):
8874
8975.. code-block :: cpp
@@ -102,11 +88,10 @@ It is possible to use ``std::shared_ptr`` as the holder, for example:
10288
10389 Compared to using ``py::classh ``, there are two noteworthy disadvantages:
10490
105- * A ``py::class_ `` for any particular C++ type ``T `` (and all its derived types)
106- can only use a single holder type. Therefore, ``std::unique_ptr<T> ``
107- cannot even be passed from C++ to Python if the ``std::shared_ptr<T> `` holder
108- is used. This will become apparent only at runtime, often through a
109- segmentation fault or double free.
91+ * Because a ``py::class_ `` for a given C++ type ``T `` can only use a
92+ single holder type, ``std::unique_ptr<T> `` cannot even be passed from C++
93+ to Python. This will become apparent only at runtime, often through a
94+ segmentation fault.
11095
11196* Similar to the ``std::unique_ptr `` holder, the handling of base-and-derived
11297 classes involves a ``reinterpret_cast `` that has strictly speaking undefined
@@ -118,9 +103,9 @@ Compared to using ``py::classh``, there are two noteworthy disadvantages:
118103Custom smart pointers
119104=====================
120105
121- For custom smart pointer, transparent conversions can be enabled
122- using a macro invocation similar to the following. It must be declared at the
123- top namespace level before any binding code:
106+ For custom smart pointers (e.g. `` c10::intrusive_ptr `` in pytorch), transparent
107+ conversions can be enabled using a macro invocation similar to the following.
108+ It must be declared at the top namespace level before any binding code:
124109
125110.. code-block :: cpp
126111
@@ -167,19 +152,28 @@ specialized:
167152 The above specialization informs pybind11 that the custom ``SmartPtr `` class
168153provides ``.get() `` functionality via ``.getPointer() ``.
169154
155+ .. note ::
156+
157+ The two noteworthy disadvantages mentioned under the ``std::shared_ptr ``
158+ section apply similarly to custom smart pointer holders, but there is no
159+ established safe alternative in this case.
160+
170161.. seealso ::
171162
172163 The file :file: `tests/test_smart_ptr.cpp ` contains a complete example
173164 that demonstrates how to work with custom reference-counting holder types
174165 in more detail.
175166
176167
177- Be careful to not undermine automatic lifetime management
178- =========================================================
168+ Be careful not to accidentally undermine automatic lifetime management
169+ ======================================================================
179170
180- One potential stumbling block when using holder types is that they need to be
181- applied consistently. Can you guess what's broken about the following binding
182- code?
171+ ``py::class_ ``-wrapped objects automatically manage the lifetime of the
172+ wrapped C++ object, in collaboration with the chosen holder type.
173+ When wrapping C++ functions involving raw pointers, care needs to be taken
174+ to not inadvertently transfer ownership, resulting in multiple Python
175+ objects acting as owners, causing heap-use-after-free or double-free errors.
176+ For example:
183177
184178.. code-block :: cpp
185179
@@ -188,7 +182,7 @@ code?
188182 class Parent {
189183 public:
190184 Parent() : child(std::make_shared<Child>()) { }
191- Child *get_child() { return child.get(); } /* Hint: ** DON'T DO THIS ** */
185+ Child *get_child() { return child.get(); } /* DANGER */
192186 private:
193187 std::shared_ptr<Child> child;
194188 };
@@ -198,7 +192,7 @@ code?
198192
199193 py::class_<Parent, std::shared_ptr<Parent>>(m, "Parent")
200194 .def(py::init<>())
201- .def("get_child", &Parent::get_child);
195+ .def("get_child", &Parent::get_child); /* PROBLEM */
202196 }
203197
204198 The following Python code will cause undefined behavior (and likely a
@@ -210,34 +204,18 @@ segmentation fault).
210204
211205 print (Parent().get_child())
212206
213- The problem is that ``Parent::get_child() `` returns a pointer to an instance of
214- ``Child ``, but the fact that this instance is already managed by
215- ``std::shared_ptr<...> `` is lost when passing raw pointers. In this case,
216- pybind11 will create a second independent ``std::shared_ptr<...> `` that also
217- claims ownership of the pointer. In the end, the object will be freed **twice **
218- since these shared pointers have no way of knowing about each other.
219-
220- There are two ways to resolve this issue:
221-
222- 1. For types that are managed by a smart pointer class, never use raw pointers
223- in function arguments or return values. In other words: always consistently
224- wrap pointers into their designated holder types (such as
225- ``std::shared_ptr<...> ``). In this case, the signature of ``get_child() ``
226- should be modified as follows:
227-
228- .. code-block :: cpp
229-
230- std::shared_ptr<Child> get_child() { return child; }
231-
232- 2. Adjust the definition of ``Child `` by specifying
233- ``std::enable_shared_from_this<T> `` (see cppreference _ for details) as a
234- base class. This adds a small bit of information to ``Child `` that allows
235- pybind11 to realize that there is already an existing
236- ``std::shared_ptr<...> `` and communicate with it. In this case, the
237- declaration of ``Child `` should look as follows:
238-
239- .. _cppreference : http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
240-
241- .. code-block :: cpp
242-
243- class Child : public std::enable_shared_from_this<Child> { };
207+ Part of the ``/* PROBLEM */ `` here is that pybind11 falls back to using
208+ ``return_value_policy::take_ownership `` as the default (see
209+ :ref: `return_value_policies `). The fact that the ``Child `` instance is
210+ already managed by ``std::shared_ptr<Child> `` is lost. Therefore pybind11
211+ will create a second independent ``std::shared_ptr<Child> `` that also
212+ claims ownership of the pointer, eventually leading to heap-use-after-free
213+ or double-free errors.
214+
215+ There are various ways to resolve this issue, either by changing
216+ the ``Child `` or ``Parent `` C++ implementations (e.g. using
217+ ``std::enable_shared_from_this<Child> `` as a base class for
218+ ``Child ``, or adding a member function to ``Parent `` that returns
219+ ``std::shared_ptr<Child> ``), or if that is not feasible, by using
220+ ``return_value_policy::reference_internal ``. What is the best approach
221+ depends on the exact situation.
0 commit comments