mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
a bit of work on the new documentation structure
This commit is contained in:
parent
c0d19192d2
commit
6ba98650e2
@ -39,7 +39,7 @@ depending on the system.
|
|||||||
If it is a typedef of the system clock, python will get datetime objects, but if
|
If it is a typedef of the system clock, python will get datetime objects, but if
|
||||||
it is a different clock they will be timedelta objects.
|
it is a different clock they will be timedelta objects.
|
||||||
|
|
||||||
Conversions Provided
|
Provided conversions
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
.. rubric:: C++ to Python
|
.. rubric:: C++ to Python
|
||||||
|
@ -1,148 +1,41 @@
|
|||||||
Type conversions
|
Type conversions
|
||||||
################
|
################
|
||||||
|
|
||||||
There are 3 mechanisms that pybind11 uses to move data between C++ and Python.
|
Apart from enabling cross-language function calls, a fundamental problem
|
||||||
We'll take a quick look at each one to get an overview of what's happening.
|
that a binding tool like pybind11 must address is to provide access to
|
||||||
|
native Python types in C++ and vice versa. There are three fundamentally
|
||||||
|
different ways to do this—which approach is preferable for a particular type
|
||||||
|
depends on the situation at hand.
|
||||||
|
|
||||||
.. rubric:: 1. Native type in C++, wrapper in Python
|
1. Use a native C++ type everywhere. In this case, the type must be wrapped
|
||||||
|
using pybind11-generated bindings so that Python can interact with it.
|
||||||
|
|
||||||
Exposing a custom C++ type using :class:`py::class_` was covered in detail in
|
2. Use a native Python type everywhere. It will need to be wrapped so that
|
||||||
the :doc:`/classes` section. There, the underlying data structure is always the
|
C++ functions can interact with it.
|
||||||
original C++ class while the :class:`py::class_` wrapper provides a Python
|
|
||||||
interface. Internally, when an object like this is sent from C++ to Python,
|
|
||||||
pybind11 will just add the outer wrapper layer over the native C++ object.
|
|
||||||
Getting it back from Python is just a matter of peeling off the wrapper.
|
|
||||||
|
|
||||||
.. rubric:: 2. Wrapper in C++, native type in Python
|
3. Use a native C++ type on the C++ side and a native Python type on the
|
||||||
|
Python side. pybind11 refers to this as a *type conversion*.
|
||||||
|
|
||||||
This is the exact opposite situation. Now, we have a type which is native to
|
Type conversions are the most "natural" option in the sense that native
|
||||||
Python, like a ``tuple`` or a ``list``. One way to get this data into C++ is
|
(non-wrapped) types are used everywhere. The main downside is that a copy
|
||||||
with the :class:`py::object` family of wrappers. These are explained in more
|
of the data must be made on every Python ↔ C++ transition: this is
|
||||||
detail in the :doc:`/advanced/pycpp/object` section. We'll just give a quick
|
needed since the C++ and Python versions of the same type generally won't
|
||||||
example here:
|
have the same memory layout.
|
||||||
|
|
||||||
.. code-block:: cpp
|
pybind11 can perform many kinds of conversions automatically. An overview
|
||||||
|
is provided in the table ":ref:`conversion_table`".
|
||||||
|
|
||||||
void print_list(py::list my_list) {
|
The following subsections discuss the differences between these options in more
|
||||||
for (auto item : my_list)
|
detail. The main focus in this section is on type conversions, which represent
|
||||||
std::cout << item << " ";
|
the last case of the above list.
|
||||||
}
|
|
||||||
|
|
||||||
.. code-block:: pycon
|
|
||||||
|
|
||||||
>>> print_list([1, 2, 3])
|
|
||||||
1 2 3
|
|
||||||
|
|
||||||
The Python ``list`` is not converted in any way -- it's just wrapped in a C++
|
|
||||||
:class:`py::list` class. At its core it's still a Python object. Copying a
|
|
||||||
:class:`py::list` will do the usual reference-counting like in Python.
|
|
||||||
Returning the object to Python will just remove the thin wrapper.
|
|
||||||
|
|
||||||
.. rubric:: 3. Converting between native C++ and Python types
|
|
||||||
|
|
||||||
In the previous two cases we had a native type in one language and a wrapper in
|
|
||||||
the other. Now, we have native types on both sides and we convert between them.
|
|
||||||
|
|
||||||
.. code-block:: cpp
|
|
||||||
|
|
||||||
void print_vector(const std::vector<int> &v) {
|
|
||||||
for (auto item : v)
|
|
||||||
std::cout << item << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
.. code-block:: pycon
|
|
||||||
|
|
||||||
>>> print_vector([1, 2, 3])
|
|
||||||
1 2 3
|
|
||||||
|
|
||||||
In this case, pybind11 will construct a new ``std::vector<int>`` and copy each
|
|
||||||
element from the Python ``list``. The newly constructed object will be passed
|
|
||||||
to ``print_vector``. The same thing happens in the other direction: a new
|
|
||||||
``list`` is made to match the value returned from C++.
|
|
||||||
|
|
||||||
Lots of these conversions are supported out of the box, as shown in the table
|
|
||||||
below. They are very convenient, but keep in mind that these conversions are
|
|
||||||
fundamentally based on copying data. This is perfectly fine for small immutable
|
|
||||||
types but it may become quite expensive for large data structures. This can be
|
|
||||||
avoided by overriding the automatic conversion with a custom wrapper (i.e. the
|
|
||||||
above-mentioned approach 1). This requires some manual effort and more details
|
|
||||||
are available in the :ref:`opaque` section.
|
|
||||||
|
|
||||||
.. rubric:: Supported automatic conversions
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
overview
|
||||||
stl
|
stl
|
||||||
functional
|
functional
|
||||||
chrono
|
chrono
|
||||||
eigen
|
eigen
|
||||||
custom
|
custom
|
||||||
|
|
||||||
The following basic data types are supported out of the box (some may require
|
|
||||||
an additional extension header to be included). To pass other data structures
|
|
||||||
as arguments and return values, refer to the section on binding :ref:`classes`.
|
|
||||||
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| Data type | Description | Header file |
|
|
||||||
+=================================+==========================+===============================+
|
|
||||||
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``std::chrono::time_point<...>``| STL date/time | :file:`pybind11/chrono.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
|
||||||
+---------------------------------+--------------------------+-------------------------------+
|
|
||||||
|
140
docs/advanced/cast/overview.rst
Normal file
140
docs/advanced/cast/overview.rst
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
Overview
|
||||||
|
########
|
||||||
|
|
||||||
|
.. rubric:: 1. Native type in C++, wrapper in Python
|
||||||
|
|
||||||
|
Exposing a custom C++ type using :class:`py::class_` was covered in detail
|
||||||
|
in the :doc:`/classes` section. There, the underlying data structure is
|
||||||
|
always the original C++ class while the :class:`py::class_` wrapper provides
|
||||||
|
a Python interface. Internally, when an object like this is sent from C++ to
|
||||||
|
Python, pybind11 will just add the outer wrapper layer over the native C++
|
||||||
|
object. Getting it back from Python is just a matter of peeling off the
|
||||||
|
wrapper.
|
||||||
|
|
||||||
|
.. rubric:: 2. Wrapper in C++, native type in Python
|
||||||
|
|
||||||
|
This is the exact opposite situation. Now, we have a type which is native to
|
||||||
|
Python, like a ``tuple`` or a ``list``. One way to get this data into C++ is
|
||||||
|
with the :class:`py::object` family of wrappers. These are explained in more
|
||||||
|
detail in the :doc:`/advanced/pycpp/object` section. We'll just give a quick
|
||||||
|
example here:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void print_list(py::list my_list) {
|
||||||
|
for (auto item : my_list)
|
||||||
|
std::cout << item << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> print_list([1, 2, 3])
|
||||||
|
1 2 3
|
||||||
|
|
||||||
|
The Python ``list`` is not converted in any way -- it's just wrapped in a C++
|
||||||
|
:class:`py::list` class. At its core it's still a Python object. Copying a
|
||||||
|
:class:`py::list` will do the usual reference-counting like in Python.
|
||||||
|
Returning the object to Python will just remove the thin wrapper.
|
||||||
|
|
||||||
|
.. rubric:: 3. Converting between native C++ and Python types
|
||||||
|
|
||||||
|
In the previous two cases we had a native type in one language and a wrapper in
|
||||||
|
the other. Now, we have native types on both sides and we convert between them.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void print_vector(const std::vector<int> &v) {
|
||||||
|
for (auto item : v)
|
||||||
|
std::cout << item << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> print_vector([1, 2, 3])
|
||||||
|
1 2 3
|
||||||
|
|
||||||
|
In this case, pybind11 will construct a new ``std::vector<int>`` and copy each
|
||||||
|
element from the Python ``list``. The newly constructed object will be passed
|
||||||
|
to ``print_vector``. The same thing happens in the other direction: a new
|
||||||
|
``list`` is made to match the value returned from C++.
|
||||||
|
|
||||||
|
Lots of these conversions are supported out of the box, as shown in the table
|
||||||
|
below. They are very convenient, but keep in mind that these conversions are
|
||||||
|
fundamentally based on copying data. This is perfectly fine for small immutable
|
||||||
|
types but it may become quite expensive for large data structures. This can be
|
||||||
|
avoided by overriding the automatic conversion with a custom wrapper (i.e. the
|
||||||
|
above-mentioned approach 1). This requires some manual effort and more details
|
||||||
|
are available in the :ref:`opaque` section.
|
||||||
|
|
||||||
|
.. _conversion_table:
|
||||||
|
|
||||||
|
List of all builtin conversions
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The following basic data types are supported out of the box (some may require
|
||||||
|
an additional extension header to be included). To pass other data structures
|
||||||
|
as arguments and return values, refer to the section on binding :ref:`classes`.
|
||||||
|
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| Data type | Description | Header file |
|
||||||
|
+=================================+==========================+===============================+
|
||||||
|
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``std::chrono::time_point<...>``| STL date/time | :file:`pybind11/chrono.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
||||||
|
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
||||||
|
+---------------------------------+--------------------------+-------------------------------+
|
@ -9,48 +9,62 @@ functions, i.e. *methods* in Python.
|
|||||||
Return value policies
|
Return value policies
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Python and C++ use wildly different ways of managing the memory and lifetime of
|
Python and C++ use fundamentally different ways of managing the memory and
|
||||||
objects managed by them. This can lead to issues when creating bindings for
|
lifetime of objects managed by them. This can lead to issues when creating
|
||||||
functions that return a non-trivial type. Just by looking at the type
|
bindings for functions that return a non-trivial type. Just by looking at the
|
||||||
information, it is not clear whether Python should take charge of the returned
|
type information, it is not clear whether Python should take charge of the
|
||||||
value and eventually free its resources, or if this is handled on the C++ side.
|
returned value and eventually free its resources, or if this is handled on the
|
||||||
For this reason, pybind11 provides a several `return value policy` annotations
|
C++ side. For this reason, pybind11 provides a several `return value policy`
|
||||||
that can be passed to the :func:`module::def` and :func:`class_::def`
|
annotations that can be passed to the :func:`module::def` and
|
||||||
functions. The default policy is :enum:`return_value_policy::automatic`.
|
:func:`class_::def` functions. The default policy is
|
||||||
|
:enum:`return_value_policy::automatic`.
|
||||||
|
|
||||||
Return value policies can also be applied to properties, in which case the
|
Return value policies are tricky, and it's very important to get them right.
|
||||||
arguments must be passed through the :class:`cpp_function` constructor:
|
Just to illustrate what can go wrong, consider the following simple example:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
class_<MyClass>(m, "MyClass")
|
/* Function declaration */
|
||||||
def_property("data"
|
Data *get_data() { return _data; /* (pointer to a static data structure) */ }
|
||||||
py::cpp_function(&MyClass::getData, py::return_value_policy::copy),
|
...
|
||||||
py::cpp_function(&MyClass::setData)
|
|
||||||
);
|
|
||||||
|
|
||||||
The following table provides an overview of the available return value policies:
|
/* Binding code */
|
||||||
|
m.def("get_data", &get_data); // <-- KABOOM, will cause crash when called from Python
|
||||||
|
|
||||||
|
What's going on here? When ``get_data()`` is called from Python, the return
|
||||||
|
value (a native C++ type) must be wrapped to turn it into a usable Python type.
|
||||||
|
In this case, the default return value policy (:enum:`return_value_policy::automatic`)
|
||||||
|
causes pybind11 to assume ownership of the static ``_data`` instance.
|
||||||
|
|
||||||
|
When Python's garbage collector eventually deletes the Python
|
||||||
|
wrapper, pybind11 will also attempt to delete the C++ instance (via ``operator
|
||||||
|
delete()``) due to the implied ownership. At this point, the entire application
|
||||||
|
will come crashing down, though errors could also be more subtle and involve
|
||||||
|
silent data corruption.
|
||||||
|
|
||||||
|
In the above example, the policy :enum:`return_value_policy::reference` should have
|
||||||
|
been specified so that the global data instance is only *referenced* without any
|
||||||
|
implied transfer of ownership, i.e.:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("get_data", &get_data, return_value_policy::reference);
|
||||||
|
|
||||||
|
On the other hand, this is not the right policy for many other situations,
|
||||||
|
where ignoring ownership could lead to resource leaks.
|
||||||
|
As a developer using pybind11, it's important to be familiar with the different
|
||||||
|
return value policies, including which situation calls for which one of them.
|
||||||
|
The following table provides an overview of available policies:
|
||||||
|
|
||||||
.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
|
.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
|
||||||
|
|
||||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
| Return value policy | Description |
|
| Return value policy | Description |
|
||||||
+==================================================+============================================================================+
|
+==================================================+============================================================================+
|
||||||
| :enum:`return_value_policy::automatic` | This is the default return value policy, which falls back to the policy |
|
|
||||||
| | :enum:`return_value_policy::take_ownership` when the return value is a |
|
|
||||||
| | pointer. Otherwise, it uses :enum:`return_value::move` or |
|
|
||||||
| | :enum:`return_value::copy` for rvalue and lvalue references, respectively. |
|
|
||||||
| | See below for a description of what all of these different policies do. |
|
|
||||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
|
||||||
| :enum:`return_value_policy::automatic_reference` | As above, but use policy :enum:`return_value_policy::reference` when the |
|
|
||||||
| | return value is a pointer. This is the default conversion policy for |
|
|
||||||
| | function arguments when calling Python functions manually from C++ code |
|
|
||||||
| | (i.e. via handle::operator()). You probably won't need to use this. |
|
|
||||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
|
||||||
| :enum:`return_value_policy::take_ownership` | Reference an existing object (i.e. do not create a new copy) and take |
|
| :enum:`return_value_policy::take_ownership` | Reference an existing object (i.e. do not create a new copy) and take |
|
||||||
| | ownership. Python will call the destructor and delete operator when the |
|
| | ownership. Python will call the destructor and delete operator when the |
|
||||||
| | object's reference count reaches zero. Undefined behavior ensues when the |
|
| | object's reference count reaches zero. Undefined behavior ensues when the |
|
||||||
| | C++ side does the same. |
|
| | C++ side does the same, or when the data was not dynamically allocated. |
|
||||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
| :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python. |
|
| :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python. |
|
||||||
| | This policy is comparably safe because the lifetimes of the two instances |
|
| | This policy is comparably safe because the lifetimes of the two instances |
|
||||||
@ -74,6 +88,28 @@ The following table provides an overview of the available return value policies:
|
|||||||
| | return value is referenced by Python. This is the default policy for |
|
| | return value is referenced by Python. This is the default policy for |
|
||||||
| | property getters created via ``def_property``, ``def_readwrite``, etc. |
|
| | property getters created via ``def_property``, ``def_readwrite``, etc. |
|
||||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::automatic` | This is the default return value policy, which falls back to the policy |
|
||||||
|
| | :enum:`return_value_policy::take_ownership` when the return value is a |
|
||||||
|
| | pointer. Otherwise, it uses :enum:`return_value::move` or |
|
||||||
|
| | :enum:`return_value::copy` for rvalue and lvalue references, respectively. |
|
||||||
|
| | See above for a description of what all of these different policies do. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::automatic_reference` | As above, but use policy :enum:`return_value_policy::reference` when the |
|
||||||
|
| | return value is a pointer. This is the default conversion policy for |
|
||||||
|
| | function arguments when calling Python functions manually from C++ code |
|
||||||
|
| | (i.e. via handle::operator()). You probably won't need to use this. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Return value policies can also be applied to properties, in which case the
|
||||||
|
arguments must be passed through the :class:`cpp_function` constructor:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class_<MyClass>(m, "MyClass")
|
||||||
|
def_property("data"
|
||||||
|
py::cpp_function(&MyClass::getData, py::return_value_policy::copy),
|
||||||
|
py::cpp_function(&MyClass::setData)
|
||||||
|
);
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
@ -82,12 +118,14 @@ The following table provides an overview of the available return value policies:
|
|||||||
non-determinism and segmentation faults, hence it is worth spending the
|
non-determinism and segmentation faults, hence it is worth spending the
|
||||||
time to understand all the different options in the table above.
|
time to understand all the different options in the table above.
|
||||||
|
|
||||||
One important aspect of the above policies is that they only apply to instances
|
.. note::
|
||||||
which pybind11 has *not* seen before, in which case the policy clarifies
|
|
||||||
essential questions about the return value's lifetime and ownership. When
|
One important aspect of the above policies is that they only apply to
|
||||||
pybind11 knows the instance already (as identified by its type and address in
|
instances which pybind11 has *not* seen before, in which case the policy
|
||||||
memory), it will return the existing Python object wrapper rather than creating
|
clarifies essential questions about the return value's lifetime and
|
||||||
a new copy.
|
ownership. When pybind11 knows the instance already (as identified by its
|
||||||
|
type and address in memory), it will return the existing Python object
|
||||||
|
wrapper rather than creating a new copy.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user