123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- STL containers
- ##############
- Automatic conversion
- ====================
- When including the additional header file :file:`pybind11/stl.h`, conversions
- between ``std::vector<>``/``std::list<>``/``std::array<>``,
- ``std::set<>``/``std::unordered_set<>``, and
- ``std::map<>``/``std::unordered_map<>`` and the Python ``list``, ``set`` and
- ``dict`` data structures are automatically enabled. The types ``std::pair<>``
- and ``std::tuple<>`` are already supported out of the box with just the core
- :file:`pybind11/pybind11.h` header.
- The major downside of these implicit conversions is that containers must be
- converted (i.e. copied) on every Python->C++ and C++->Python transition, which
- can have implications on the program semantics and performance. Please read the
- next sections for more details and alternative approaches that avoid this.
- .. note::
- Arbitrary nesting of any of these types is possible.
- .. seealso::
- The file :file:`tests/test_stl.cpp` contains a complete
- example that demonstrates how to pass STL data types in more detail.
- .. _cpp17_container_casters:
- C++17 library containers
- ========================
- The :file:`pybind11/stl.h` header also includes support for ``std::optional<>``
- and ``std::variant<>``. These require a C++17 compiler and standard library.
- In C++14 mode, ``std::experimental::optional<>`` is supported if available.
- Various versions of these containers also exist for C++11 (e.g. in Boost).
- pybind11 provides an easy way to specialize the ``type_caster`` for such
- types:
- .. code-block:: cpp
- // `boost::optional` as an example -- can be any `std::optional`-like container
- namespace pybind11 { namespace detail {
- template <typename T>
- struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {};
- }}
- The above should be placed in a header file and included in all translation units
- where automatic conversion is needed. Similarly, a specialization can be provided
- for custom variant types:
- .. code-block:: cpp
- // `boost::variant` as an example -- can be any `std::variant`-like container
- namespace pybind11 { namespace detail {
- template <typename... Ts>
- struct type_caster<boost::variant<Ts...>> : variant_caster<boost::variant<Ts...>> {};
- // Specifies the function used to visit the variant -- `apply_visitor` instead of `visit`
- template <>
- struct visit_helper<boost::variant> {
- template <typename... Args>
- static auto call(Args &&...args) -> decltype(boost::apply_visitor(args...)) {
- return boost::apply_visitor(args...);
- }
- };
- }} // namespace pybind11::detail
- The ``visit_helper`` specialization is not required if your ``name::variant`` provides
- a ``name::visit()`` function. For any other function name, the specialization must be
- included to tell pybind11 how to visit the variant.
- .. note::
- pybind11 only supports the modern implementation of ``boost::variant``
- which makes use of variadic templates. This requires Boost 1.56 or newer.
- Additionally, on Windows, MSVC 2017 is required because ``boost::variant``
- falls back to the old non-variadic implementation on MSVC 2015.
- .. _opaque:
- Making opaque types
- ===================
- pybind11 heavily relies on a template matching mechanism to convert parameters
- and return values that are constructed from STL data types such as vectors,
- linked lists, hash tables, etc. This even works in a recursive manner, for
- instance to deal with lists of hash maps of pairs of elementary and custom
- types, etc.
- However, a fundamental limitation of this approach is that internal conversions
- between Python and C++ types involve a copy operation that prevents
- pass-by-reference semantics. What does this mean?
- Suppose we bind the following function
- .. code-block:: cpp
- void append_1(std::vector<int> &v) {
- v.push_back(1);
- }
- and call it from Python, the following happens:
- .. code-block:: pycon
- >>> v = [5, 6]
- >>> append_1(v)
- >>> print(v)
- [5, 6]
- As you can see, when passing STL data structures by reference, modifications
- are not propagated back the Python side. A similar situation arises when
- exposing STL data structures using the ``def_readwrite`` or ``def_readonly``
- functions:
- .. code-block:: cpp
- /* ... definition ... */
- class MyClass {
- std::vector<int> contents;
- };
- /* ... binding code ... */
- py::class_<MyClass>(m, "MyClass")
- .def(py::init<>())
- .def_readwrite("contents", &MyClass::contents);
- In this case, properties can be read and written in their entirety. However, an
- ``append`` operation involving such a list type has no effect:
- .. code-block:: pycon
- >>> m = MyClass()
- >>> m.contents = [5, 6]
- >>> print(m.contents)
- [5, 6]
- >>> m.contents.append(7)
- >>> print(m.contents)
- [5, 6]
- Finally, the involved copy operations can be costly when dealing with very
- large lists. To deal with all of the above situations, pybind11 provides a
- macro named ``PYBIND11_MAKE_OPAQUE(T)`` that disables the template-based
- conversion machinery of types, thus rendering them *opaque*. The contents of
- opaque objects are never inspected or extracted, hence they *can* be passed by
- reference. For instance, to turn ``std::vector<int>`` into an opaque type, add
- the declaration
- .. code-block:: cpp
- PYBIND11_MAKE_OPAQUE(std::vector<int>);
- before any binding code (e.g. invocations to ``class_::def()``, etc.). This
- macro must be specified at the top level (and outside of any namespaces), since
- it instantiates a partial template overload. If your binding code consists of
- multiple compilation units, it must be present in every file (typically via a
- common header) preceding any usage of ``std::vector<int>``. Opaque types must
- also have a corresponding ``class_`` declaration to associate them with a name
- in Python, and to define a set of available operations, e.g.:
- .. code-block:: cpp
- py::class_<std::vector<int>>(m, "IntVector")
- .def(py::init<>())
- .def("clear", &std::vector<int>::clear)
- .def("pop_back", &std::vector<int>::pop_back)
- .def("__len__", [](const std::vector<int> &v) { return v.size(); })
- .def("__iter__", [](std::vector<int> &v) {
- return py::make_iterator(v.begin(), v.end());
- }, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
- // ....
- Please take a look at the :ref:`macro_notes` before using the
- ``PYBIND11_MAKE_OPAQUE`` macro.
- .. seealso::
- The file :file:`tests/test_opaque_types.cpp` contains a complete
- example that demonstrates how to create and expose opaque types using
- pybind11 in more detail.
- .. _stl_bind:
- Binding STL containers
- ======================
- The ability to expose STL containers as native Python objects is a fairly
- common request, hence pybind11 also provides an optional header file named
- :file:`pybind11/stl_bind.h` that does exactly this. The mapped containers try
- to match the behavior of their native Python counterparts as much as possible.
- The following example showcases usage of :file:`pybind11/stl_bind.h`:
- .. code-block:: cpp
- // Don't forget this
- #include <pybind11/stl_bind.h>
- PYBIND11_MAKE_OPAQUE(std::vector<int>);
- PYBIND11_MAKE_OPAQUE(std::map<std::string, double>);
- // ...
- // later in binding code:
- py::bind_vector<std::vector<int>>(m, "VectorInt");
- py::bind_map<std::map<std::string, double>>(m, "MapStringDouble");
- When binding STL containers pybind11 considers the types of the container's
- elements to decide whether the container should be confined to the local module
- (via the :ref:`module_local` feature). If the container element types are
- anything other than already-bound custom types bound without
- ``py::module_local()`` the container binding will have ``py::module_local()``
- applied. This includes converting types such as numeric types, strings, Eigen
- types; and types that have not yet been bound at the time of the stl container
- binding. This module-local binding is designed to avoid potential conflicts
- between module bindings (for example, from two separate modules each attempting
- to bind ``std::vector<int>`` as a python type).
- It is possible to override this behavior to force a definition to be either
- module-local or global. To do so, you can pass the attributes
- ``py::module_local()`` (to make the binding module-local) or
- ``py::module_local(false)`` (to make the binding global) into the
- ``py::bind_vector`` or ``py::bind_map`` arguments:
- .. code-block:: cpp
- py::bind_vector<std::vector<int>>(m, "VectorInt", py::module_local(false));
- Note, however, that such a global binding would make it impossible to load this
- module at the same time as any other pybind module that also attempts to bind
- the same container type (``std::vector<int>`` in the above example).
- See :ref:`module_local` for more details on module-local bindings.
- .. seealso::
- The file :file:`tests/test_stl_binders.cpp` shows how to use the
- convenience STL container wrappers.
|