stl.rst revision 11986
111986Sandreas.sandberg@arm.comSTL containers
211986Sandreas.sandberg@arm.com##############
311986Sandreas.sandberg@arm.com
411986Sandreas.sandberg@arm.comAutomatic conversion
511986Sandreas.sandberg@arm.com====================
611986Sandreas.sandberg@arm.com
711986Sandreas.sandberg@arm.comWhen including the additional header file :file:`pybind11/stl.h`, conversions
811986Sandreas.sandberg@arm.combetween ``std::vector<>``, ``std::list<>``, ``std::set<>``, and ``std::map<>``
911986Sandreas.sandberg@arm.comand the Python ``list``, ``set`` and ``dict`` data structures are automatically
1011986Sandreas.sandberg@arm.comenabled. The types ``std::pair<>`` and ``std::tuple<>`` are already supported
1111986Sandreas.sandberg@arm.comout of the box with just the core :file:`pybind11/pybind11.h` header.
1211986Sandreas.sandberg@arm.com
1311986Sandreas.sandberg@arm.comThe major downside of these implicit conversions is that containers must be
1411986Sandreas.sandberg@arm.comconverted (i.e. copied) on every Python->C++ and C++->Python transition, which
1511986Sandreas.sandberg@arm.comcan have implications on the program semantics and performance. Please read the
1611986Sandreas.sandberg@arm.comnext sections for more details and alternative approaches that avoid this.
1711986Sandreas.sandberg@arm.com
1811986Sandreas.sandberg@arm.com.. note::
1911986Sandreas.sandberg@arm.com
2011986Sandreas.sandberg@arm.com    Arbitrary nesting of any of these types is possible.
2111986Sandreas.sandberg@arm.com
2211986Sandreas.sandberg@arm.com.. seealso::
2311986Sandreas.sandberg@arm.com
2411986Sandreas.sandberg@arm.com    The file :file:`tests/test_python_types.cpp` contains a complete
2511986Sandreas.sandberg@arm.com    example that demonstrates how to pass STL data types in more detail.
2611986Sandreas.sandberg@arm.com
2711986Sandreas.sandberg@arm.com.. _opaque:
2811986Sandreas.sandberg@arm.com
2911986Sandreas.sandberg@arm.comMaking opaque types
3011986Sandreas.sandberg@arm.com===================
3111986Sandreas.sandberg@arm.com
3211986Sandreas.sandberg@arm.compybind11 heavily relies on a template matching mechanism to convert parameters
3311986Sandreas.sandberg@arm.comand return values that are constructed from STL data types such as vectors,
3411986Sandreas.sandberg@arm.comlinked lists, hash tables, etc. This even works in a recursive manner, for
3511986Sandreas.sandberg@arm.cominstance to deal with lists of hash maps of pairs of elementary and custom
3611986Sandreas.sandberg@arm.comtypes, etc.
3711986Sandreas.sandberg@arm.com
3811986Sandreas.sandberg@arm.comHowever, a fundamental limitation of this approach is that internal conversions
3911986Sandreas.sandberg@arm.combetween Python and C++ types involve a copy operation that prevents
4011986Sandreas.sandberg@arm.compass-by-reference semantics. What does this mean?
4111986Sandreas.sandberg@arm.com
4211986Sandreas.sandberg@arm.comSuppose we bind the following function
4311986Sandreas.sandberg@arm.com
4411986Sandreas.sandberg@arm.com.. code-block:: cpp
4511986Sandreas.sandberg@arm.com
4611986Sandreas.sandberg@arm.com    void append_1(std::vector<int> &v) {
4711986Sandreas.sandberg@arm.com       v.push_back(1);
4811986Sandreas.sandberg@arm.com    }
4911986Sandreas.sandberg@arm.com
5011986Sandreas.sandberg@arm.comand call it from Python, the following happens:
5111986Sandreas.sandberg@arm.com
5211986Sandreas.sandberg@arm.com.. code-block:: pycon
5311986Sandreas.sandberg@arm.com
5411986Sandreas.sandberg@arm.com   >>> v = [5, 6]
5511986Sandreas.sandberg@arm.com   >>> append_1(v)
5611986Sandreas.sandberg@arm.com   >>> print(v)
5711986Sandreas.sandberg@arm.com   [5, 6]
5811986Sandreas.sandberg@arm.com
5911986Sandreas.sandberg@arm.comAs you can see, when passing STL data structures by reference, modifications
6011986Sandreas.sandberg@arm.comare not propagated back the Python side. A similar situation arises when
6111986Sandreas.sandberg@arm.comexposing STL data structures using the ``def_readwrite`` or ``def_readonly``
6211986Sandreas.sandberg@arm.comfunctions:
6311986Sandreas.sandberg@arm.com
6411986Sandreas.sandberg@arm.com.. code-block:: cpp
6511986Sandreas.sandberg@arm.com
6611986Sandreas.sandberg@arm.com    /* ... definition ... */
6711986Sandreas.sandberg@arm.com
6811986Sandreas.sandberg@arm.com    class MyClass {
6911986Sandreas.sandberg@arm.com        std::vector<int> contents;
7011986Sandreas.sandberg@arm.com    };
7111986Sandreas.sandberg@arm.com
7211986Sandreas.sandberg@arm.com    /* ... binding code ... */
7311986Sandreas.sandberg@arm.com
7411986Sandreas.sandberg@arm.com    py::class_<MyClass>(m, "MyClass")
7511986Sandreas.sandberg@arm.com        .def(py::init<>)
7611986Sandreas.sandberg@arm.com        .def_readwrite("contents", &MyClass::contents);
7711986Sandreas.sandberg@arm.com
7811986Sandreas.sandberg@arm.comIn this case, properties can be read and written in their entirety. However, an
7911986Sandreas.sandberg@arm.com``append`` operation involving such a list type has no effect:
8011986Sandreas.sandberg@arm.com
8111986Sandreas.sandberg@arm.com.. code-block:: pycon
8211986Sandreas.sandberg@arm.com
8311986Sandreas.sandberg@arm.com   >>> m = MyClass()
8411986Sandreas.sandberg@arm.com   >>> m.contents = [5, 6]
8511986Sandreas.sandberg@arm.com   >>> print(m.contents)
8611986Sandreas.sandberg@arm.com   [5, 6]
8711986Sandreas.sandberg@arm.com   >>> m.contents.append(7)
8811986Sandreas.sandberg@arm.com   >>> print(m.contents)
8911986Sandreas.sandberg@arm.com   [5, 6]
9011986Sandreas.sandberg@arm.com
9111986Sandreas.sandberg@arm.comFinally, the involved copy operations can be costly when dealing with very
9211986Sandreas.sandberg@arm.comlarge lists. To deal with all of the above situations, pybind11 provides a
9311986Sandreas.sandberg@arm.commacro named ``PYBIND11_MAKE_OPAQUE(T)`` that disables the template-based
9411986Sandreas.sandberg@arm.comconversion machinery of types, thus rendering them *opaque*. The contents of
9511986Sandreas.sandberg@arm.comopaque objects are never inspected or extracted, hence they *can* be passed by
9611986Sandreas.sandberg@arm.comreference. For instance, to turn ``std::vector<int>`` into an opaque type, add
9711986Sandreas.sandberg@arm.comthe declaration
9811986Sandreas.sandberg@arm.com
9911986Sandreas.sandberg@arm.com.. code-block:: cpp
10011986Sandreas.sandberg@arm.com
10111986Sandreas.sandberg@arm.com    PYBIND11_MAKE_OPAQUE(std::vector<int>);
10211986Sandreas.sandberg@arm.com
10311986Sandreas.sandberg@arm.combefore any binding code (e.g. invocations to ``class_::def()``, etc.). This
10411986Sandreas.sandberg@arm.commacro must be specified at the top level (and outside of any namespaces), since
10511986Sandreas.sandberg@arm.comit instantiates a partial template overload. If your binding code consists of
10611986Sandreas.sandberg@arm.commultiple compilation units, it must be present in every file preceding any
10711986Sandreas.sandberg@arm.comusage of ``std::vector<int>``. Opaque types must also have a corresponding
10811986Sandreas.sandberg@arm.com``class_`` declaration to associate them with a name in Python, and to define a
10911986Sandreas.sandberg@arm.comset of available operations, e.g.:
11011986Sandreas.sandberg@arm.com
11111986Sandreas.sandberg@arm.com.. code-block:: cpp
11211986Sandreas.sandberg@arm.com
11311986Sandreas.sandberg@arm.com    py::class_<std::vector<int>>(m, "IntVector")
11411986Sandreas.sandberg@arm.com        .def(py::init<>())
11511986Sandreas.sandberg@arm.com        .def("clear", &std::vector<int>::clear)
11611986Sandreas.sandberg@arm.com        .def("pop_back", &std::vector<int>::pop_back)
11711986Sandreas.sandberg@arm.com        .def("__len__", [](const std::vector<int> &v) { return v.size(); })
11811986Sandreas.sandberg@arm.com        .def("__iter__", [](std::vector<int> &v) {
11911986Sandreas.sandberg@arm.com           return py::make_iterator(v.begin(), v.end());
12011986Sandreas.sandberg@arm.com        }, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
12111986Sandreas.sandberg@arm.com        // ....
12211986Sandreas.sandberg@arm.com
12311986Sandreas.sandberg@arm.comThe ability to expose STL containers as native Python objects is a fairly
12411986Sandreas.sandberg@arm.comcommon request, hence pybind11 also provides an optional header file named
12511986Sandreas.sandberg@arm.com:file:`pybind11/stl_bind.h` that does exactly this. The mapped containers try
12611986Sandreas.sandberg@arm.comto match the behavior of their native Python counterparts as much as possible.
12711986Sandreas.sandberg@arm.com
12811986Sandreas.sandberg@arm.comThe following example showcases usage of :file:`pybind11/stl_bind.h`:
12911986Sandreas.sandberg@arm.com
13011986Sandreas.sandberg@arm.com.. code-block:: cpp
13111986Sandreas.sandberg@arm.com
13211986Sandreas.sandberg@arm.com    // Don't forget this
13311986Sandreas.sandberg@arm.com    #include <pybind11/stl_bind.h>
13411986Sandreas.sandberg@arm.com
13511986Sandreas.sandberg@arm.com    PYBIND11_MAKE_OPAQUE(std::vector<int>);
13611986Sandreas.sandberg@arm.com    PYBIND11_MAKE_OPAQUE(std::map<std::string, double>);
13711986Sandreas.sandberg@arm.com
13811986Sandreas.sandberg@arm.com    // ...
13911986Sandreas.sandberg@arm.com
14011986Sandreas.sandberg@arm.com    // later in binding code:
14111986Sandreas.sandberg@arm.com    py::bind_vector<std::vector<int>>(m, "VectorInt");
14211986Sandreas.sandberg@arm.com    py::bind_map<std::map<std::string, double>>(m, "MapStringDouble");
14311986Sandreas.sandberg@arm.com
14411986Sandreas.sandberg@arm.comPlease take a look at the :ref:`macro_notes` before using the
14511986Sandreas.sandberg@arm.com``PYBIND11_MAKE_OPAQUE`` macro.
14611986Sandreas.sandberg@arm.com
14711986Sandreas.sandberg@arm.com.. seealso::
14811986Sandreas.sandberg@arm.com
14911986Sandreas.sandberg@arm.com    The file :file:`tests/test_opaque_types.cpp` contains a complete
15011986Sandreas.sandberg@arm.com    example that demonstrates how to create and expose opaque types using
15111986Sandreas.sandberg@arm.com    pybind11 in more detail.
15211986Sandreas.sandberg@arm.com
15311986Sandreas.sandberg@arm.com    The file :file:`tests/test_stl_binders.cpp` shows how to use the
15411986Sandreas.sandberg@arm.com    convenience STL container wrappers.
155