You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/advanced/classes.rst
+130-11
Original file line number
Diff line number
Diff line change
@@ -64,10 +64,10 @@ helper class that is defined as follows:
64
64
65
65
.. code-block:: cpp
66
66
67
-
class PyAnimal : public Animal {
67
+
class PyAnimal : public py::wrapper<Animal> {
68
68
public:
69
69
/* Inherit the constructors */
70
-
using Animal::Animal;
70
+
using py::wrapper<Animal>::wrapper;
71
71
72
72
/* Trampoline (need one for each virtual function) */
73
73
std::string go(int n_times) override {
@@ -89,6 +89,8 @@ function* slots, which defines the name of function in Python. This is required
89
89
when the C++ and Python versions of the
90
90
function have different names, e.g. ``operator()`` vs ``__call__``.
91
91
92
+
The base class ``py::wrapper<>`` is optional, but is recommended as it allows us to attach the lifetime of Python objects directly to C++ objects, explained in :ref:`virtual_inheritance_lifetime`.
93
+
92
94
The binding code also needs a few minor adaptations (highlighted):
93
95
94
96
.. code-block:: cpp
@@ -230,15 +232,15 @@ override the ``name()`` method):
230
232
231
233
.. code-block:: cpp
232
234
233
-
class PyAnimal : public Animal {
235
+
class PyAnimal : public py::wrapper<Animal> {
234
236
public:
235
-
using Animal::Animal; // Inherit constructors
237
+
using py::wrapper<Animal>::wrapper; // Inherit constructors
@@ -1080,3 +1082,120 @@ appropriate derived-class pointer (e.g. using
1080
1082
more complete example, including a demonstration of how to provide
1081
1083
automatic downcasting for an entire class hierarchy without
1082
1084
writing one get() function for each class.
1085
+
1086
+
.. _virtual_inheritance_lifetime:
1087
+
1088
+
Virtual Inheritance and Lifetime
1089
+
================================
1090
+
1091
+
When an instance of a Python subclass of a ``pybind11``-bound C++ class is instantiated, there are effectively two "portions": the C++ portion of the base class's alias instance, and the Python portion (``__dict__``) of the derived class instance.
1092
+
Generally, the lifetime of an instance of a Python subclass of a ``pybind11``-bound C++ class will not pose an issue as long as the instance is owned in Python - that is, you can call virtual methods from C++ or Python and have the correct behavior.
1093
+
1094
+
However, if this Python-constructed instance is passed to C++ such that there are no other Python references, then C++ must keep the Python portion of the instance alive until either (a) the C++ reference is destroyed via ``delete`` or (b) the object is passed back to Python. ``pybind11`` supports both cases, but **only** when (i) the class inherits from :class:`py::wrapper`, (ii) there is only single-inheritance in the bound C++ classes, and (iii) the holder type for the class is either :class:`std::shared_ptr` (suggested) or :class:`std::unique_ptr` (default).
1095
+
1096
+
.. seealso::
1097
+
1098
+
:ref:`holders` has more information regaring holders and how general ownership transfer should function.
1099
+
1100
+
When ``pybind11`` detects case (a), it will store a reference to the Python object in :class:`py::wrapper` using :class:`py::object`, such that if the instance is deleted by C++, then it will also release the Python object (via :func:`py::wrapper::~wrapper()`). The wrapper will have a unique reference to the Python object (as any other circumstance would trigger case (b)), so the Python object should be destroyed immediately upon the instance's destruction.
1101
+
This will be a cyclic reference per Python's memory management, but this is not an issue as the memory is now managed via C++.
1102
+
1103
+
For :class:`std::shared_ptr`, this case is detected by placing a shim :func:`__del__` method on the Python subclass when ``pybind11`` detects an instance being created. This shim will check for case (a), and if it holds, will "resurrect" since it created a new reference using :class:`py::object`.
1104
+
1105
+
For :class:`std::unique_ptr`, this case is detected when calling `py::cast<unique_ptr<T>>`, which itself implies ownership transfer.
1106
+
1107
+
.. seealso::
1108
+
1109
+
See :ref:`unique_ptr_ownership` for information about how ownership can be transferred via a cast or argument involving ``unique_ptr<Type>``.
1110
+
1111
+
When ``pybind11`` detects case (b) (e.g. ``py::cast()`` is called to convert a C++ instance to `py::object`) and (a) has previously occurred, such that C++ manages the lifetime of the object, then :class:`py::wrapper` will release the Python reference to allow Python to manage the lifetime of the object.
1112
+
1113
+
.. note::
1114
+
1115
+
This mechanism will be generally robust against reference cycles in Python as this couples the two "portions"; however, it does **not** protect against reference cycles with :class:`std::shared_ptr`. You should take care and use :class:`std::weak_ref` or raw pointers (with care) when needed.
1116
+
1117
+
.. note::
1118
+
1119
+
There will a slight difference in destructor order if the complete instance is destroyed in C++ or in Python; however, this difference will only be a difference in ordering in when :func:`py::wrapper::~wrapper()` (and your alias destructor) is called in relation to :func:`__del__` for the subclass. For more information, see the documentation comments for :class:`py::wrapper`.
1120
+
1121
+
For this example, we will build upon the above code for ``Animal`` with alias ``PyAnimal``, and the Python subclass ``Cat``, but will introduce a situation where C++ may have sole ownership: a container. In this case, it will be ``Cage``, which can contain or release an animal.
1122
+
1123
+
.. note::
1124
+
1125
+
For lifetime, it is important to use a more Python-friendly holder, which in this case would be :class:`std::shared_ptr`, permitting an ease to share ownership.
Normally, if you keep the object alive in Python, then no additional instrumentation is necessary:
1184
+
1185
+
.. code-block:: pycon
1186
+
1187
+
>>> cat = Cat()
1188
+
>>> c.add(cat) # This object lives in both Python and C++.
1189
+
>>> c.release().go(2)
1190
+
meow! meow!
1191
+
1192
+
However, if you pass an instance that Python later wishes to destroy, without :class:`py::wrapper`, we would get an error that ``go`` is not implented,
1193
+
as the `Cat` portion would have been destroyed and no longer visible for the trampoline. With the wrapper, ``pybind11`` will intercept this event and keep the Python portion alive:
1194
+
1195
+
.. code-block:: pycon
1196
+
1197
+
>>> c.add(Cat())
1198
+
>>> c.release().go(2)
1199
+
meow! meow!
1200
+
1201
+
Note that both the C++ and Python portion of ``cat`` will be destroyed once ``cage`` is destroyed.
Copy file name to clipboardExpand all lines: docs/advanced/smart_ptrs.rst
+123-19
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,17 @@
1
-
Smart pointers
2
-
##############
1
+
.. _holders:
2
+
3
+
Smart pointers and holders
4
+
##########################
5
+
6
+
Holders
7
+
=======
8
+
9
+
The binding generator for classes, :class:`class_`, can be passed a template
10
+
type that denotes a special *holder* type that is used to manage references to
11
+
the object. If no such holder type template argument is given, the default for
12
+
a type named ``Type`` is ``std::unique_ptr<Type>``, which means that the object
13
+
is deallocated when Python's reference count goes to zero. It is possible to switch to other types of reference counting wrappers or smart
14
+
pointers, which is useful in codebases that rely on them, such as ``std::shared_ptr<Type>``, or even a custom type.
3
15
4
16
std::unique_ptr
5
17
===============
@@ -15,31 +27,100 @@ instances wrapped in C++11 unique pointers, like so
15
27
16
28
m.def("create_example", &create_example);
17
29
18
-
In other words, there is nothing special that needs to be done. While returning
19
-
unique pointers in this way is allowed, it is *illegal* to use them as function
20
-
arguments. For instance, the following function signature cannot be processed
21
-
by pybind11.
30
+
In other words, there is nothing special that needs to be done.
31
+
32
+
.. _unique_ptr_ownership:
33
+
34
+
Transferring ownership
35
+
----------------------
36
+
37
+
It is also possible to pass ``std::unique_ptr<Type>`` as a function
38
+
argument, or use ``py::cast<unique_ptr<Type>>(std::move(obj))``. Note that this tells pybind11 to not manage the memory for this object, and delegate that to ``std::unique_ptr<Type>``.
39
+
For instance, the following function signature can be processed by pybind11:
The above signature would imply that Python needs to give up ownership of an
28
-
object that is passed to this function, which is generally not possible (for
29
-
instance, the object might be referenced elsewhere).
45
+
The above signature does imply that Python needs to give up ownership of an
46
+
object that is passed to this function. There are two ways to do this:
47
+
48
+
1. Simply pass the object in. The reference count of the object can be greater than one (non-unique) when passing the object in. **However**, you *must* ensure that the object has only **one** reference when C++ (which owns the C++ object).
49
+
50
+
To expand on this, when transferring ownership for ``std::unique_ptr``, this means that Pybind11 no longer owns the reference, which means that if C++ lets the ``std::unique_ptr`` destruct but if there is a dangling reference in Python, then you will encounter undefined behavior.
51
+
52
+
Examples situations:
53
+
54
+
* The C++ function is terminal (i.e. will destroy the object once it completes). This is generally not an issue unless a Python portion of the object has a non-trivial ``__del__`` method.
55
+
* The Python object is passed to a C++ container which only tracks ``std::unique_ptr<Type>``. If the container goes out of scope, the Python object reference will be invalid.
56
+
57
+
.. note::
58
+
59
+
For polymorphic types that inherit from :class:`py::wrapper`, ``pybind11`` *can* warn about these situations.
60
+
You may enable this behavior with ``#define PYBIND11_WARN_DANGLING_UNIQUE_PYREF``. This will print a warning to ``std::err`` if this case is detected.
61
+
62
+
2. Pass a Python "move container" (a mutable object that can "release" the reference to the object). This can be a single-item list, or any Python class / instance that has the field ``_is_move_container = True`` and has a ``release()`` function.
63
+
64
+
.. note::
65
+
66
+
When using a move container, this expects that the provided object is a **unique** reference, or will throw an error otherwise. This is a little more verbose, but will make debugging *much* easier.
obj.do_something(); // `obj` will be destroyed when the function exits.
74
+
}
75
+
76
+
// Binding
77
+
py::class_<Example> example(m, "Example");
78
+
m.def("terminal_func", &terminal_func);
79
+
80
+
In Python, say you would normally do this:
81
+
82
+
.. code-block:: pycon
83
+
84
+
>>> obj = Example()
85
+
>>> terminal_func(obj)
86
+
87
+
As mentioned in the comment, you *must* ensure that `obj` is not used past this invocation, as the underlying data has been destroyed. To be more careful, you may "move" the object. The following will throw an error:
88
+
89
+
.. code-block:: pycon
90
+
91
+
>>> obj = Example()
92
+
>>> terminal_func([obj])
93
+
94
+
However, this will work, using a "move" container:
95
+
96
+
.. code-block:: pycon
97
+
98
+
>>> obj = Example()
99
+
>>> obj_move = [obj]
100
+
>>> del obj
101
+
>>> terminal_func(obj_move)
102
+
>>> print(obj_move) # Reference will have been removed.
103
+
[None]
104
+
105
+
or even:
106
+
107
+
.. code-block:: pycon
108
+
109
+
>>> terminal_func([Example()])
110
+
111
+
.. note::
112
+
113
+
``terminal_func(Example())`` also works, but still leaves a dangling reference, which is only a problem if it is polymorphic and has a non-trivial ``__del__`` method.
114
+
115
+
.. warning::
116
+
117
+
This reference counting mechanism is **not** robust aganist cyclic references. If you need some sort of cyclic reference, *please* consider using ``weakref.ref`` in Python.
30
118
31
119
std::shared_ptr
32
120
===============
33
121
34
-
The binding generator for classes, :class:`class_`, can be passed a template
35
-
type that denotes a special *holder* type that is used to manage references to
36
-
the object. If no such holder type template argument is given, the default for
37
-
a type named ``Type`` is ``std::unique_ptr<Type>``, which means that the object
38
-
is deallocated when Python's reference count goes to zero.
39
-
40
-
It is possible to switch to other types of reference counting wrappers or smart
41
-
pointers, which is useful in codebases that rely on them. For instance, the
42
-
following snippet causes ``std::shared_ptr`` to be used instead.
122
+
If you have an existing code base with ``std::shared_ptr``, or you wish to enable reference counting in C++ as well, then you may use this type as a holder.
123
+
As an example, the following snippet causes ``std::shared_ptr`` to be used instead.
43
124
44
125
.. code-block:: cpp
45
126
@@ -111,6 +192,12 @@ There are two ways to resolve this issue:
111
192
112
193
class Child : public std::enable_shared_from_this<Child> { };
113
194
195
+
.. seealso::
196
+
197
+
While ownership transfer is generally not an issue with ``std::shared_ptr<Type>``, it becomes an issue when an instance of a Python subclass of a pybind11 class is effectively managed by C++ (e.g. all live references to the object are from C++, and all reference in Python have "died").
198
+
199
+
See :ref:`virtual_inheritance_lifetime` for more information.
200
+
114
201
.. _smart_pointers:
115
202
116
203
Custom smart pointers
@@ -147,7 +234,7 @@ Please take a look at the :ref:`macro_notes` before using this feature.
147
234
148
235
By default, pybind11 assumes that your custom smart pointer has a standard
149
236
interface, i.e. provides a ``.get()`` member function to access the underlying
150
-
raw pointer. If this is not the case, pybind11's ``holder_helper`` must be
237
+
raw pointer, and a ``.release()`` member function for move-only holders. If this is not the case, pybind11's ``holder_helper`` must be
151
238
specialized:
152
239
153
240
.. code-block:: cpp
@@ -171,3 +258,20 @@ provides ``.get()`` functionality via ``.getPointer()``.
171
258
The file :file:`tests/test_smart_ptr.cpp` contains a complete example
172
259
that demonstrates how to work with custom reference-counting holder types
173
260
in more detail.
261
+
262
+
.. warning::
263
+
264
+
Holder type conversion (see :ref:`smart_ptrs_casting`) and advanced ownership transfer (see :ref:`virtual_inheritance_lifetime`) is **not** supported for custom shared pointer types, due to constraints on dynamic type erasure.
265
+
266
+
.. _smart_ptrs_casting:
267
+
268
+
Casting smart pointers
269
+
======================
270
+
271
+
As shown in the :ref:`conversion_table`, you may cast to any of the available holders (e.g. ``py::cast<std::shared_ptr<Type>>(obj)``) that can properly provide access to the underlying holder.
272
+
273
+
``pybind11`` will raise an error if there is an incompatible cast. You may of course cast to the exact same holder type. You may also move a ``std::unique_ptr<Type>`` into a ``std::shared_ptr<Type>``, as this is allowed. **However**, you may not convert a ``std::shared_ptr<Type>`` to a ``std::unique_ptr<Type>`` as you cannot release an object that is managed by ``std::shared_ptr<Type>``.
274
+
275
+
Additionally, conversion to ``std::unique_ptr<Type, Deleter>`` is not supported if ``Deleter`` is not ``std::default_deleter<Type>``.
276
+
277
+
Conversion to a different custom smart pointer is not supported.
0 commit comments