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. 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 struct type_caster> : optional_caster> {}; }} 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 struct type_caster> : variant_caster> {}; // Specifies the function used to visit the variant -- `apply_visitor` instead of `visit` template <> struct visit_helper { template 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 &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 contents; }; /* ... binding code ... */ py::class_(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`` into an opaque type, add the declaration .. code-block:: cpp PYBIND11_MAKE_OPAQUE(std::vector); 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``. 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_>(m, "IntVector") .def(py::init<>()) .def("clear", &std::vector::clear) .def("pop_back", &std::vector::pop_back) .def("__len__", [](const std::vector &v) { return v.size(); }) .def("__iter__", [](std::vector &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_MAKE_OPAQUE(std::vector); PYBIND11_MAKE_OPAQUE(std::map); // ... // later in binding code: py::bind_vector>(m, "VectorInt"); py::bind_map>(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`` 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>(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`` 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.