@@ -552,15 +552,150 @@ and the Python ``list``, ``set`` and ``dict`` data structures are automatically
552
552
enabled. The types ``std::pair<> `` and ``std::tuple<> `` are already supported
553
553
out of the box with just the core :file: `pybind11/pybind11.h ` header.
554
554
555
+ The major downside of these implicit conversions is that containers must be
556
+ converted (i.e. copied) on every Python->C++ and C++->Python transition, which
557
+ can have implications on the program semantics and performance. Please read the
558
+ next sections for more details and alternative approaches that avoid this.
559
+
555
560
.. note ::
556
561
557
- Arbitrary nesting of any of these types is supported .
562
+ Arbitrary nesting of any of these types is possible .
558
563
559
564
.. seealso ::
560
565
561
566
The file :file: `tests/test_python_types.cpp ` contains a complete
562
567
example that demonstrates how to pass STL data types in more detail.
563
568
569
+ .. _opaque :
570
+
571
+ Treating STL data structures as opaque objects
572
+ ==============================================
573
+
574
+ pybind11 heavily relies on a template matching mechanism to convert parameters
575
+ and return values that are constructed from STL data types such as vectors,
576
+ linked lists, hash tables, etc. This even works in a recursive manner, for
577
+ instance to deal with lists of hash maps of pairs of elementary and custom
578
+ types, etc.
579
+
580
+ However, a fundamental limitation of this approach is that internal conversions
581
+ between Python and C++ types involve a copy operation that prevents
582
+ pass-by-reference semantics. What does this mean?
583
+
584
+ Suppose we bind the following function
585
+
586
+ .. code-block :: cpp
587
+
588
+ void append_1(std::vector<int> &v) {
589
+ v.push_back(1);
590
+ }
591
+
592
+ and call it from Python, the following happens:
593
+
594
+ .. code-block :: pycon
595
+
596
+ >>> v = [5, 6]
597
+ >>> append_1(v)
598
+ >>> print(v)
599
+ [5, 6]
600
+
601
+ As you can see, when passing STL data structures by reference, modifications
602
+ are not propagated back the Python side. A similar situation arises when
603
+ exposing STL data structures using the ``def_readwrite `` or ``def_readonly ``
604
+ functions:
605
+
606
+ .. code-block :: cpp
607
+
608
+ /* ... definition ... */
609
+
610
+ class MyClass {
611
+ std::vector<int> contents;
612
+ };
613
+
614
+ /* ... binding code ... */
615
+
616
+ py::class_<MyClass>(m, "MyClass")
617
+ .def(py::init<>)
618
+ .def_readwrite("contents", &MyClass::contents);
619
+
620
+ In this case, properties can be read and written in their entirety. However, an
621
+ ``append `` operaton involving such a list type has no effect:
622
+
623
+ .. code-block :: pycon
624
+
625
+ >>> m = MyClass()
626
+ >>> m.contents = [5, 6]
627
+ >>> print(m.contents)
628
+ [5, 6]
629
+ >>> m.contents.append(7)
630
+ >>> print(m.contents)
631
+ [5, 6]
632
+
633
+ Finally, the involved copy operations can be costly when dealing with very
634
+ large lists. To deal with all of the above situations, pybind11 provides a
635
+ macro named ``PYBIND11_MAKE_OPAQUE(T) `` that disables the template-based
636
+ conversion machinery of types, thus rendering them *opaque *. The contents of
637
+ opaque objects are never inspected or extracted, hence they *can * be passed by
638
+ reference. For instance, to turn ``std::vector<int> `` into an opaque type, add
639
+ the declaration
640
+
641
+ .. code-block :: cpp
642
+
643
+ PYBIND11_MAKE_OPAQUE(std::vector<int>);
644
+
645
+ before any binding code (e.g. invocations to ``class_::def() ``, etc.). This
646
+ macro must be specified at the top level (and outside of any namespaces), since
647
+ it instantiates a partial template overload. If your binding code consists of
648
+ multiple compilation units, it must be present in every file preceding any
649
+ usage of ``std::vector<int> ``. Opaque types must also have a corresponding
650
+ ``class_ `` declaration to associate them with a name in Python, and to define a
651
+ set of available operations, e.g.:
652
+
653
+ .. code-block :: cpp
654
+
655
+ py::class_<std::vector<int>>(m, "IntVector")
656
+ .def(py::init<>())
657
+ .def("clear", &std::vector<int>::clear)
658
+ .def("pop_back", &std::vector<int>::pop_back)
659
+ .def("__len__", [](const std::vector<int> &v) { return v.size(); })
660
+ .def("__iter__", [](std::vector<int> &v) {
661
+ return py::make_iterator(v.begin(), v.end());
662
+ }, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
663
+ // ....
664
+
665
+ The ability to expose STL containers as native Python objects is a fairly
666
+ common request, hence pybind11 also provides an optional header file named
667
+ :file: `pybind11/stl_bind.h ` that does exactly this. The mapped containers try
668
+ to match the behavior of their native Python counterparts as much as possible.
669
+
670
+ The following example showcases usage of :file: `pybind11/stl_bind.h `:
671
+
672
+ .. code-block :: cpp
673
+
674
+ // Don't forget this
675
+ #include <pybind11/stl_bind.h>
676
+
677
+ PYBIND11_MAKE_OPAQUE(std::vector<int>);
678
+ PYBIND11_MAKE_OPAQUE(std::map<std::string, double>);
679
+
680
+ // ...
681
+
682
+ // later in binding code:
683
+ py::bind_vector<std::vector<int>>(m, "VectorInt");
684
+ py::bind_map<std::map<std::string, double>>(m, "MapStringDouble");
685
+
686
+ Please take a look at the :ref: `macro_notes ` before using the
687
+ ``PYBIND11_MAKE_OPAQUE `` macro.
688
+
689
+ .. seealso ::
690
+
691
+ The file :file: `tests/test_opaque_types.cpp ` contains a complete
692
+ example that demonstrates how to create and expose opaque types using
693
+ pybind11 in more detail.
694
+
695
+ The file :file: `tests/test_stl_binders.cpp ` shows how to use the
696
+ convenience STL container wrappers.
697
+
698
+
564
699
Binding sequence data types, iterators, the slicing protocol, etc.
565
700
==================================================================
566
701
@@ -1094,108 +1229,6 @@ section.
1094
1229
The ``py::exception `` wrapper for creating custom exceptions cannot (yet)
1095
1230
be used as a base type.
1096
1231
1097
- .. _opaque :
1098
-
1099
- Treating STL data structures as opaque objects
1100
- ==============================================
1101
-
1102
- pybind11 heavily relies on a template matching mechanism to convert parameters
1103
- and return values that are constructed from STL data types such as vectors,
1104
- linked lists, hash tables, etc. This even works in a recursive manner, for
1105
- instance to deal with lists of hash maps of pairs of elementary and custom
1106
- types, etc.
1107
-
1108
- However, a fundamental limitation of this approach is that internal conversions
1109
- between Python and C++ types involve a copy operation that prevents
1110
- pass-by-reference semantics. What does this mean?
1111
-
1112
- Suppose we bind the following function
1113
-
1114
- .. code-block :: cpp
1115
-
1116
- void append_1(std::vector<int> &v) {
1117
- v.push_back(1);
1118
- }
1119
-
1120
- and call it from Python, the following happens:
1121
-
1122
- .. code-block :: pycon
1123
-
1124
- >>> v = [5, 6]
1125
- >>> append_1(v)
1126
- >>> print(v)
1127
- [5, 6]
1128
-
1129
- As you can see, when passing STL data structures by reference, modifications
1130
- are not propagated back the Python side. A similar situation arises when
1131
- exposing STL data structures using the ``def_readwrite `` or ``def_readonly ``
1132
- functions:
1133
-
1134
- .. code-block :: cpp
1135
-
1136
- /* ... definition ... */
1137
-
1138
- class MyClass {
1139
- std::vector<int> contents;
1140
- };
1141
-
1142
- /* ... binding code ... */
1143
-
1144
- py::class_<MyClass>(m, "MyClass")
1145
- .def(py::init<>)
1146
- .def_readwrite("contents", &MyClass::contents);
1147
-
1148
- In this case, properties can be read and written in their entirety. However, an
1149
- ``append `` operaton involving such a list type has no effect:
1150
-
1151
- .. code-block :: pycon
1152
-
1153
- >>> m = MyClass()
1154
- >>> m.contents = [5, 6]
1155
- >>> print(m.contents)
1156
- [5, 6]
1157
- >>> m.contents.append(7)
1158
- >>> print(m.contents)
1159
- [5, 6]
1160
-
1161
- To deal with both of the above situations, pybind11 provides a macro named
1162
- ``PYBIND11_MAKE_OPAQUE(T) `` that disables the template-based conversion
1163
- machinery of types, thus rendering them *opaque *. The contents of opaque
1164
- objects are never inspected or extracted, hence they can be passed by
1165
- reference. For instance, to turn ``std::vector<int> `` into an opaque type, add
1166
- the declaration
1167
-
1168
- .. code-block :: cpp
1169
-
1170
- PYBIND11_MAKE_OPAQUE(std::vector<int>);
1171
-
1172
- before any binding code (e.g. invocations to ``class_::def() ``, etc.). This
1173
- macro must be specified at the top level, since instantiates a partial template
1174
- overload. If your binding code consists of multiple compilation units, it must
1175
- be present in every file preceding any usage of ``std::vector<int> ``. Opaque
1176
- types must also have a corresponding ``class_ `` declaration to associate them
1177
- with a name in Python, and to define a set of available operations:
1178
-
1179
- .. code-block :: cpp
1180
-
1181
- py::class_<std::vector<int>>(m, "IntVector")
1182
- .def(py::init<>())
1183
- .def("clear", &std::vector<int>::clear)
1184
- .def("pop_back", &std::vector<int>::pop_back)
1185
- .def("__len__", [](const std::vector<int> &v) { return v.size(); })
1186
- .def("__iter__", [](std::vector<int> &v) {
1187
- return py::make_iterator(v.begin(), v.end());
1188
- }, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
1189
- // ....
1190
-
1191
- Please take a look at the :ref: `macro_notes ` before using this feature.
1192
-
1193
- .. seealso ::
1194
-
1195
- The file :file: `tests/test_opaque_types.cpp ` contains a complete
1196
- example that demonstrates how to create and expose opaque types using
1197
- pybind11 in more detail.
1198
-
1199
1232
.. _eigen :
1200
1233
1201
1234
Transparent conversion of dense and sparse Eigen data types
0 commit comments