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