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
int8_t, uint8_t 8-bit integers pybind11/pybind11.h
int16_t, uint16_t 16-bit integers pybind11/pybind11.h
int32_t, uint32_t 32-bit integers pybind11/pybind11.h
int64_t, uint64_t 64-bit integers pybind11/pybind11.h
ssize_t, size_t Platform-dependent size pybind11/pybind11.h
float, double Floating point types pybind11/pybind11.h
bool Two-state Boolean type pybind11/pybind11.h
char Character literal pybind11/pybind11.h
char16_t UTF-16 character literal pybind11/pybind11.h
char32_t UTF-32 character literal pybind11/pybind11.h
wchar_t Wide character literal pybind11/pybind11.h
const char * UTF-8 string literal pybind11/pybind11.h
const char16_t * UTF-16 string literal pybind11/pybind11.h
const char32_t * UTF-32 string literal pybind11/pybind11.h
const wchar_t * Wide string literal pybind11/pybind11.h
std::string STL dynamic UTF-8 string pybind11/pybind11.h
std::u16string STL dynamic UTF-16 string pybind11/pybind11.h
std::u32string STL dynamic UTF-32 string pybind11/pybind11.h
std::wstring STL dynamic wide string pybind11/pybind11.h
std::string_view, std::u16string_view, etc. STL C++17 string views pybind11/pybind11.h
std::pair<T1, T2> Pair of two custom types pybind11/pybind11.h
std::tuple<...> Arbitrary tuple of types pybind11/pybind11.h
std::reference_wrapper<...> Reference type wrapper pybind11/pybind11.h
std::complex<T> Complex numbers pybind11/complex.h
std::array<T, Size> STL static array pybind11/stl.h
std::vector<T> STL dynamic array pybind11/stl.h
std::deque<T> STL double-ended queue pybind11/stl.h
std::valarray<T> STL value array pybind11/stl.h
std::list<T> STL linked list pybind11/stl.h
std::map<T1, T2> STL ordered map pybind11/stl.h
std::unordered_map<T1, T2> STL unordered map pybind11/stl.h
std::set<T> STL ordered set pybind11/stl.h
std::unordered_set<T> STL unordered set pybind11/stl.h
std::optional<T> STL optional type (C++17) pybind11/stl.h
std::experimental::optional<T> STL optional type (exp.) pybind11/stl.h
std::variant<...> Type-safe union (C++17) pybind11/stl.h
std::function<...> STL polymorphic function pybind11/functional.h
std::chrono::duration<...> STL time duration pybind11/chrono.h
std::chrono::time_point<...> STL date/time pybind11/chrono.h
Eigen::Matrix<...> Eigen: dense matrix pybind11/eigen.h
Eigen::Map<...> Eigen: mapped memory pybind11/eigen.h
Eigen::SparseMatrix<...> Eigen: sparse matrix pybind11/eigen.h