Overview¶
1. Native type in C++, wrapper in Python
Exposing a custom C++ type using py::class_
was covered in detail
in the Object-oriented code section. There, the underlying data structure is
always the original C++ class while the py::class_
wrapper provides
a Python interface. Internally, when an object like this is sent from C++ to
Python, pybind11 will just add the outer wrapper layer over the native C++
object. Getting it back from Python is just a matter of peeling off the
wrapper.
2. Wrapper in C++, native type in Python
This is the exact opposite situation. Now, we have a type which is native to
Python, like a tuple
or a list
. One way to get this data into C++ is
with the py::object
family of wrappers. These are explained in more
detail in the Python types section. We’ll just give a quick
example here:
void print_list(py::list my_list) {
for (auto item : my_list)
std::cout << item << " ";
}
>>> print_list([1, 2, 3])
1 2 3
The Python list
is not converted in any way – it’s just wrapped in a C++
py::list
class. At its core it’s still a Python object. Copying a
py::list
will do the usual reference-counting like in Python.
Returning the object to Python will just remove the thin wrapper.
3. Converting between native C++ and Python types
In the previous two cases we had a native type in one language and a wrapper in the other. Now, we have native types on both sides and we convert between them.
void print_vector(const std::vector<int> &v) {
for (auto item : v)
std::cout << item << "\n";
}
>>> print_vector([1, 2, 3])
1 2 3
In this case, pybind11 will construct a new std::vector<int>
and copy each
element from the Python list
. The newly constructed object will be passed
to print_vector
. The same thing happens in the other direction: a new
list
is made to match the value returned from C++.
Lots of these conversions are supported out of the box, as shown in the table below. They are very convenient, but keep in mind that these conversions are fundamentally based on copying data. This is perfectly fine for small immutable types but it may become quite expensive for large data structures. This can be avoided by overriding the automatic conversion with a custom wrapper (i.e. the above-mentioned approach 1). This requires some manual effort and more details are available in the Making opaque types section.
List of all builtin conversions¶
The following basic data types are supported out of the box (some may require an additional extension header to be included). To pass other data structures as arguments and return values, refer to the section on binding Object-oriented code.
Data type |
Description |
Header file |
---|---|---|
|
8-bit integers |
|
|
16-bit integers |
|
|
32-bit integers |
|
|
64-bit integers |
|
|
Platform-dependent size |
|
|
Floating point types |
|
|
Two-state Boolean type |
|
|
Character literal |
|
|
UTF-16 character literal |
|
|
UTF-32 character literal |
|
|
Wide character literal |
|
|
UTF-8 string literal |
|
|
UTF-16 string literal |
|
|
UTF-32 string literal |
|
|
Wide string literal |
|
|
STL dynamic UTF-8 string |
|
|
STL dynamic UTF-16 string |
|
|
STL dynamic UTF-32 string |
|
|
STL dynamic wide string |
|
|
STL C++17 string views |
|
|
Pair of two custom types |
|
|
Arbitrary tuple of types |
|
|
Reference type wrapper |
|
|
Complex numbers |
|
|
STL static array |
|
|
STL dynamic array |
|
|
STL double-ended queue |
|
|
STL value array |
|
|
STL linked list |
|
|
STL ordered map |
|
|
STL unordered map |
|
|
STL ordered set |
|
|
STL unordered set |
|
|
STL optional type (C++17) |
|
|
STL optional type (exp.) |
|
|
Type-safe union (C++17) |
|
|
STL path (C++17) 1 |
|
|
STL polymorphic function |
|
|
STL time duration |
|
|
STL date/time |
|
|
Eigen: dense matrix |
|
|
Eigen: mapped memory |
|
|
Eigen: sparse matrix |
|
- 1
std::filesystem::path
is converted topathlib.Path
andos.PathLike
is converted tostd::filesystem::path
.