Seamless operability between C++11 and Python for creating Python bindings of existing C++ code
—
The pybind11 type system provides automatic conversion between C++ and Python types, with support for custom type casters and various casting policies. This system handles the complex task of marshalling data between the two languages transparently.
Built-in conversions for fundamental C++ and Python types.
// Casting functions
template<typename T>
T cast(const handle &obj);
template<typename T>
handle cast(T &&value, return_value_policy policy = return_value_policy::automatic);
template<typename T>
object cast(T &&value, return_value_policy policy = return_value_policy::automatic);
// Casting with explicit policy
template<typename T>
T cast(const handle &obj, return_value_policy policy);C++ wrapper classes for Python built-in types, providing seamless integration.
class str : public object {
public:
str(const char *c = "");
str(const std::string &s);
operator std::string() const;
const char* c_str() const;
};
class bytes : public object {
public:
bytes(const char *c);
bytes(const std::string &s);
operator std::string() const;
const char* c_str() const;
};
class int_ : public object {
public:
int_(int value);
int_(long value);
operator int() const;
operator long() const;
};
class float_ : public object {
public:
float_(double value);
operator double() const;
};
class bool_ : public object {
public:
bool_(bool value);
operator bool() const;
};Wrapper classes for Python container types.
class list : public object {
public:
list();
list(size_t size);
size_t size() const;
bool empty() const;
template<typename T>
void append(T &&val);
template<typename T>
void insert(size_t index, T &&val);
object operator[](size_t index) const;
void clear();
};
class tuple : public object {
public:
tuple();
tuple(size_t size);
size_t size() const;
object operator[](size_t index) const;
};
class dict : public object {
public:
dict();
size_t size() const;
bool empty() const;
bool contains(const object &key) const;
object operator[](const object &key) const;
void clear();
list keys() const;
list values() const;
list items() const;
};
class set : public object {
public:
set();
size_t size() const;
bool empty() const;
bool contains(const object &key) const;
void add(const object &key);
void clear();
};
class slice : public object {
public:
slice(ssize_t start, ssize_t stop, ssize_t step = 1);
ssize_t start() const;
ssize_t stop() const;
ssize_t step() const;
};Control how return values are handled when crossing the C++/Python boundary.
enum class return_value_policy {
/** Automatic policy selection (default) */
automatic = 0,
/** Copy the return value */
copy,
/** Move the return value */
move,
/** Return a reference (dangerous if object lifetime not managed) */
reference,
/** Return a reference, keep parent object alive */
reference_internal,
/** Transfer ownership to Python (for pointers) */
take_ownership
};Special types for handling function arguments and keyword arguments.
class args : public tuple {
// Represents *args in Python function calls
public:
args(const tuple &tuple);
};
class kwargs : public dict {
// Represents **kwargs in Python function calls
public:
kwargs(const dict &dict);
};
class capsule : public object {
// Python capsule for passing opaque C pointers
public:
capsule(const void *value, const char *name = nullptr);
capsule(const void *value, const char *name, void (*destructor)(void *));
template<typename T>
T *get_pointer() const;
};Framework for defining custom type conversion between C++ and Python types.
// Type caster base template (specialized for custom types)
template<typename T>
struct type_caster {
// Must be specialized for custom types
// Provides load() and cast() methods
};
// Macro for simple type casters
#define PYBIND11_TYPE_CASTER(type, py_name) \
protected: \
type value; \
public: \
static constexpr auto name = py_name; \
template<typename T_, enable_if_t<std::is_same_v<type, remove_cv_t<T_>>, int> = 0> \
static handle cast(T_ *src, return_value_policy policy, handle parent) { \
/* Implementation */ \
} \
template<typename T_, enable_if_t<std::is_same_v<type, remove_cv_t<T_>>, int> = 0> \
static handle cast(T_ &&src, return_value_policy policy, handle parent) { \
/* Implementation */ \
} \
bool load(handle src, bool convert) { \
/* Implementation */ \
} \
operator type*() { return &value; } \
operator type&() { return value; }
// Create type caster instance
template<typename T>
auto make_caster(T &&value) -> type_caster<T>;Utility functions for type checking and conversion.
// Type checking
template<typename T>
bool isinstance(handle obj);
template<typename T>
bool isinstance(handle obj, handle type);
// Attribute access
template<typename T>
T getattr(handle obj, const char *name);
template<typename T>
T getattr(handle obj, const char *name, handle default_);
bool hasattr(handle obj, const char *name);
template<typename T>
void setattr(handle obj, const char *name, T &&value);
void delattr(handle obj, const char *name);
// Item access (for containers)
template<typename T>
T getitem(handle obj, handle key);
template<typename T>
void setitem(handle obj, handle key, T &&value);
void delitem(handle obj, handle key);Support for Python's buffer protocol for efficient data exchange.
class buffer_info {
public:
void *ptr; // Pointer to buffer data
ssize_t itemsize; // Size of individual items
std::string format; // Buffer format string
ssize_t ndim; // Number of dimensions
std::vector<ssize_t> shape; // Shape of buffer
std::vector<ssize_t> strides; // Strides for each dimension
buffer_info(void *ptr, ssize_t itemsize, const std::string &format,
ssize_t ndim, std::vector<ssize_t> shape,
std::vector<ssize_t> strides);
};
// Buffer protocol implementation
template<typename T>
buffer_info get_buffer_info(T *ptr, ssize_t size);#include <pybind11/pybind11.h>
namespace py = pybind11;
// Automatic conversion
std::string process_string(const std::string& input) {
return "Processed: " + input;
}
PYBIND11_MODULE(example, m) {
// String automatically converted between std::string and Python str
m.def("process_string", &process_string);
}py::list create_list() {
py::list result;
result.append("hello");
result.append(42);
result.append(3.14);
return result;
}
py::dict create_dict() {
py::dict result;
result["name"] = "pybind11";
result["version"] = "3.0.1";
return result;
}
PYBIND11_MODULE(example, m) {
m.def("create_list", &create_list);
m.def("create_dict", &create_dict);
}// Custom C++ type
struct Point {
double x, y;
};
namespace pybind11 { namespace detail {
template <> struct type_caster<Point> {
public:
PYBIND11_TYPE_CASTER(Point, _("Point"));
bool load(handle src, bool) {
if (!py::isinstance<py::sequence>(src))
return false;
auto seq = py::reinterpret_borrow<py::sequence>(src);
if (seq.size() != 2)
return false;
value.x = seq[0].cast<double>();
value.y = seq[1].cast<double>();
return true;
}
static handle cast(Point src, return_value_policy, handle) {
return py::make_tuple(src.x, src.y).release();
}
};
}}
// Now Point can be used directly in function signatures
Point add_points(const Point& a, const Point& b) {
return {a.x + b.x, a.y + b.y};
}
PYBIND11_MODULE(example, m) {
m.def("add_points", &add_points);
}class DataHolder {
std::vector<double> data;
public:
const std::vector<double>& get_data() const { return data; }
std::vector<double>& get_data_mutable() { return data; }
};
PYBIND11_MODULE(example, m) {
py::class_<DataHolder>(m, "DataHolder")
// Return reference, keeping parent alive
.def("get_data", &DataHolder::get_data,
py::return_value_policy::reference_internal)
// Return copy (safer but slower)
.def("get_data_copy", &DataHolder::get_data,
py::return_value_policy::copy);
}namespace pybind11 {
// Core casting types
template<typename T> struct type_caster;
class buffer_info;
// Return value policies
enum class return_value_policy;
// Python object wrappers
class str;
class bytes;
class int_;
class float_;
class bool_;
class list;
class tuple;
class dict;
class set;
class slice;
class capsule;
// Special argument types
class args;
class kwargs;
// Type traits and utilities
template<typename T> struct handle_type_name;
template<typename T> constexpr bool is_pyobject_v;
}Install with Tessl CLI
npx tessl i tessl/pypi-pybind11