Seamless operability between C++11 and Python for creating Python bindings of existing C++ code
—
pybind11 provides advanced features for complex binding scenarios including inheritance, virtual methods, operators, enumerations, smart pointer integration, and embedding Python in C++ applications.
Support for C++ inheritance hierarchies and virtual method overriding from Python.
// Virtual method overriding support
#define PYBIND11_OVERRIDE(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, __VA_ARGS__)
#define PYBIND11_OVERRIDE_PURE(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE_PURE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, __VA_ARGS__)
// Trampoline class base for smart holder compatibility
class trampoline_self_life_support {
// Base class for trampoline classes when using smart_holder
};
// Multiple inheritance support
class multiple_inheritance {
// Template parameter to enable multiple inheritance
};
// Dynamic attribute support
class dynamic_attr {
// Template parameter to enable dynamic attribute access
};Comprehensive support for C++ operator overloading in Python.
// Arithmetic operators
auto operator+(const T& a, const T& b);
auto operator-(const T& a, const T& b);
auto operator*(const T& a, const T& b);
auto operator/(const T& a, const T& b);
auto operator%(const T& a, const T& b);
// Comparison operators
auto operator==(const T& a, const T& b);
auto operator!=(const T& a, const T& b);
auto operator<(const T& a, const T& b);
auto operator<=(const T& a, const T& b);
auto operator>(const T& a, const T& b);
auto operator>=(const T& a, const T& b);
// Unary operators
auto operator-(const T& a); // Negation
auto operator+(const T& a); // Unary plus
auto operator!(const T& a); // Logical not
auto operator~(const T& a); // Bitwise not
// Compound assignment
auto operator+=(T& a, const T& b);
auto operator-=(T& a, const T& b);
auto operator*=(T& a, const T& b);
auto operator/=(T& a, const T& b);
// Stream operators
auto operator<<(std::ostream& os, const T& obj);
auto operator>>(std::istream& is, T& obj);
// Subscript operator
auto operator[](T& obj, const Key& key);
// Call operator
auto operator()(T& obj, Args... args);
// Self operators (using 'self' placeholder)
py::self + py::self;
py::self - py::self;
py::self * py::self;
py::self / py::self;
py::self == py::self;
py::self != py::self;
py::self < py::self;Support for C++ enumerations with various options.
template<typename Type>
class enum_ : public class_<Type> {
public:
// Constructor
enum_(const handle &scope, const char *name);
// Add enum values
enum_ &value(const char *name, Type value, const char *doc = nullptr);
// Export values to enclosing scope
enum_ &export_values();
// Arithmetic operations on enums (optional)
enum_ &def_arithmetic();
};
// Scoped enums (enum class)
template<typename Type>
enum_<Type> bind_enum(module_ &m, const char *name);Advanced smart pointer support and lifetime management.
// Smart pointer holders
template<typename T>
class holder_type<std::unique_ptr<T>>;
template<typename T>
class holder_type<std::shared_ptr<T>>;
// Smart holder (experimental advanced holder)
template<typename T>
class smart_holder;
// Holder type specification in class binding
py::class_<MyClass, std::shared_ptr<MyClass>>(m, "MyClass");
py::class_<MyClass, std::unique_ptr<MyClass>>(m, "MyClass");
// Return value policies for smart pointers
return_value_policy::take_ownership; // Transfer unique_ptr ownership
return_value_policy::copy; // Copy shared_ptr
return_value_policy::reference_internal; // Keep parent aliveEmbed Python interpreter in C++ applications.
// Python interpreter management
class scoped_interpreter {
public:
scoped_interpreter(bool init_signal_handlers = true,
int argc = 0, const char * const *argv = nullptr,
bool add_program_dir_to_path = true);
~scoped_interpreter();
// Non-copyable, non-movable
scoped_interpreter(const scoped_interpreter&) = delete;
scoped_interpreter& operator=(const scoped_interpreter&) = delete;
};
// Manual interpreter control
void initialize_interpreter(bool init_signal_handlers = true,
int argc = 0, const char * const *argv = nullptr,
bool add_program_dir_to_path = true);
void finalize_interpreter();
bool is_interpreter_running();
// Code execution
object exec(const str &expr, object global = globals(), object local = object());
object exec(const char *expr, object global = globals(), object local = object());
object eval(const str &expr, object global = globals(), object local = object());
object eval(const char *expr, object global = globals(), object local = object());
template<typename... Args>
object eval_file(const str &fname, Args &&...args);Advanced function binding options and call policies.
// Function naming and documentation
auto name(const char *name);
auto doc(const char *doc);
// Argument handling
auto arg(const char *name);
template<typename T>
auto arg_v(const char *name, T &&value, const char *doc = nullptr);
// Call policies and lifetime management
auto keep_alive(size_t nurse, size_t patient);
auto keep_alive_impl(size_t nurse, size_t patient);
// Function relationship
auto sibling(handle other_function);
auto is_method(handle self);
auto is_operator();
// Advanced function options
auto prepend(); // Prepend to overload chain
auto scope(handle scope); // Set function scopeBinding global variables and constants to Python.
// Module-level attributes
template<typename T>
module_ &attr(const char *name, T &&value);
// Read-only attributes
template<typename T>
module_ &def_readonly(const char *name, const T *value);
// Read-write attributes
template<typename T>
module_ &def_readwrite(const char *name, T *value);Advanced Global Interpreter Lock (GIL) management for multi-threading.
// GIL management classes
class gil_scoped_acquire {
public:
gil_scoped_acquire();
~gil_scoped_acquire();
// Non-copyable, non-movable
gil_scoped_acquire(const gil_scoped_acquire&) = delete;
};
class gil_scoped_release {
public:
gil_scoped_release();
~gil_scoped_release();
// Non-copyable, non-movable
gil_scoped_release(const gil_scoped_release&) = delete;
};
// GIL-free function marking
class gil_not_used {
// Mark module as not using GIL
};
// Multiple interpreter support
class multiple_interpreters {
// Mark module as supporting multiple interpreters
};Advanced class customization options.
// Custom metaclass support
template<typename T>
class metaclass {
public:
metaclass(handle meta);
};
// Property descriptors with custom behavior
template<typename Getter, typename Setter>
class custom_property {
public:
custom_property(Getter getter, Setter setter);
};
// Dynamic attribute access
template<typename T>
struct dynamic_attr_support {
// Enable __setattr__ and __getattr__
};#include <pybind11/pybind11.h>
namespace py = pybind11;
// Base class with virtual methods
class Animal {
public:
virtual ~Animal() = default;
virtual std::string speak() const = 0;
virtual std::string type() const { return "Animal"; }
};
// Trampoline class for Python inheritance
class PyAnimal : public Animal {
public:
using Animal::Animal;
std::string speak() const override {
PYBIND11_OVERRIDE_PURE(std::string, Animal, speak);
}
std::string type() const override {
PYBIND11_OVERRIDE(std::string, Animal, type);
}
};
// Derived class
class Dog : public Animal {
public:
std::string speak() const override { return "Woof!"; }
std::string type() const override { return "Dog"; }
};
PYBIND11_MODULE(example, m) {
py::class_<Animal, PyAnimal>(m, "Animal")
.def(py::init<>())
.def("speak", &Animal::speak)
.def("type", &Animal::type);
py::class_<Dog>(m, "Dog", py::base<Animal>())
.def(py::init<>());
}
// Python usage:
// class Cat(Animal):
// def speak(self):
// return "Meow!"
//
// cat = Cat()
// print(cat.speak()) # "Meow!"#include <pybind11/pybind11.h>
#include <pybind11/operators.h>
namespace py = pybind11;
class Vector2D {
public:
double x, y;
Vector2D(double x = 0, double y = 0) : x(x), y(y) {}
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
Vector2D operator-(const Vector2D& other) const {
return Vector2D(x - other.x, y - other.y);
}
Vector2D operator*(double scalar) const {
return Vector2D(x * scalar, y * scalar);
}
bool operator==(const Vector2D& other) const {
return x == other.x && y == other.y;
}
double length() const {
return std::sqrt(x * x + y * y);
}
};
PYBIND11_MODULE(example, m) {
py::class_<Vector2D>(m, "Vector2D")
.def(py::init<double, double>())
.def_readwrite("x", &Vector2D::x)
.def_readwrite("y", &Vector2D::y)
.def("length", &Vector2D::length)
// Bind operators
.def(py::self + py::self)
.def(py::self - py::self)
.def(py::self * double())
.def(double() * py::self)
.def(py::self == py::self)
.def("__repr__", [](const Vector2D& v) {
return "Vector2D(" + std::to_string(v.x) + ", " + std::to_string(v.y) + ")";
});
}#include <pybind11/pybind11.h>
namespace py = pybind11;
enum class Color { Red, Green, Blue };
enum LogLevel {
DEBUG = 0,
INFO = 1,
WARNING = 2,
ERROR = 3
};
PYBIND11_MODULE(example, m) {
// Scoped enum (enum class)
py::enum_<Color>(m, "Color")
.value("Red", Color::Red)
.value("Green", Color::Green)
.value("Blue", Color::Blue)
.export_values(); // Optional: export to module scope
// Traditional enum with arithmetic operations
py::enum_<LogLevel>(m, "LogLevel")
.value("DEBUG", DEBUG)
.value("INFO", INFO)
.value("WARNING", WARNING)
.value("ERROR", ERROR)
.def_arithmetic(); // Enable arithmetic operations
}
// Python usage:
// print(Color.Red) # Color.Red
// print(LogLevel.INFO + 1) # 2 (if arithmetic enabled)#include <pybind11/pybind11.h>
#include <memory>
namespace py = pybind11;
class Resource {
public:
Resource(const std::string& name) : name_(name) {}
const std::string& name() const { return name_; }
private:
std::string name_;
};
// Factory function returning unique_ptr
std::unique_ptr<Resource> create_resource(const std::string& name) {
return std::make_unique<Resource>(name);
}
// Factory function returning shared_ptr
std::shared_ptr<Resource> create_shared_resource(const std::string& name) {
return std::make_shared<Resource>(name);
}
PYBIND11_MODULE(example, m) {
// Bind class with shared_ptr holder
py::class_<Resource, std::shared_ptr<Resource>>(m, "Resource")
.def(py::init<const std::string&>())
.def("name", &Resource::name);
m.def("create_resource", &create_resource);
m.def("create_shared_resource", &create_shared_resource);
}#include <pybind11/pybind11.h>
#include <pybind11/embed.h>
namespace py = pybind11;
int main() {
// Start Python interpreter
py::scoped_interpreter guard{};
// Execute Python code
py::exec("print('Hello from embedded Python!')");
// Execute Python expressions and get results
py::object result = py::eval("2 + 3");
std::cout << "2 + 3 = " << result.cast<int>() << std::endl;
// Import and use Python modules
py::object math = py::module_::import("math");
py::object pi = math.attr("pi");
std::cout << "Pi = " << pi.cast<double>() << std::endl;
// Execute Python file
py::eval_file("script.py");
// Create Python functions from C++
py::exec(R"(
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
)");
py::object fib = py::globals()["fibonacci"];
py::object result_fib = fib(10);
std::cout << "Fibonacci(10) = " << result_fib.cast<int>() << std::endl;
return 0;
}#include <pybind11/pybind11.h>
#include <thread>
namespace py = pybind11;
void cpu_intensive_work() {
// Release GIL for CPU-intensive work
py::gil_scoped_release release;
// Perform CPU-intensive computation
for (int i = 0; i < 1000000; ++i) {
// Some computation
}
// GIL automatically reacquired when 'release' goes out of scope
}
void call_python_from_thread(py::function callback) {
std::thread worker([callback]() {
// Acquire GIL in thread
py::gil_scoped_acquire acquire;
try {
callback("Hello from thread!");
}
catch (py::error_already_set& e) {
std::cerr << "Python exception in thread: " << e.what() << std::endl;
}
});
worker.join();
}
PYBIND11_MODULE(example, m) {
m.def("cpu_intensive_work", &cpu_intensive_work);
m.def("call_python_from_thread", &call_python_from_thread);
}#include <pybind11/pybind11.h>
namespace py = pybind11;
class DynamicClass {
public:
DynamicClass() = default;
// Optional: custom attribute access
py::object get_attr(const std::string& name) {
auto it = attrs_.find(name);
if (it != attrs_.end()) {
return it->second;
}
throw py::attribute_error("Attribute '" + name + "' not found");
}
void set_attr(const std::string& name, py::object value) {
attrs_[name] = value;
}
private:
std::map<std::string, py::object> attrs_;
};
PYBIND11_MODULE(example, m) {
py::class_<DynamicClass>(m, "DynamicClass", py::dynamic_attr())
.def(py::init<>())
.def("get_attr", &DynamicClass::get_attr)
.def("set_attr", &DynamicClass::set_attr);
}
// Python usage:
// obj = DynamicClass()
// obj.new_attribute = "Hello" # Dynamic attribute assignment
// print(obj.new_attribute) # "Hello"Automatic conversion between C++ chrono types and Python datetime objects.
// Include pybind11/chrono.h for automatic conversions:
// std::chrono::duration<Rep, Period> <-> datetime.timedelta
// std::chrono::time_point<Clock, Duration> <-> datetime.datetime
// Supported chrono types
using std::chrono::system_clock;
using std::chrono::steady_clock;
using std::chrono::high_resolution_clock;
using std::chrono::duration;
using std::chrono::time_point;
// Common duration types automatically supported
using std::chrono::nanoseconds;
using std::chrono::microseconds;
using std::chrono::milliseconds;
using std::chrono::seconds;
using std::chrono::minutes;
using std::chrono::hours;Execute Python code and evaluate expressions from C++.
// Evaluation modes
enum eval_mode {
eval_expr, // Evaluate expression, return result
eval_single_statement, // Execute single statement, return none
eval_statements // Execute multiple statements, return none
};
// Evaluation functions
template<eval_mode mode = eval_expr>
object eval(const str &expr, object global = globals(), object local = object());
template<eval_mode mode = eval_expr>
object eval(const char *expr, object global = globals(), object local = object());
// File execution
template<eval_mode mode = eval_statements, typename... Args>
object eval_file(const str &fname, Args &&...args);Automatic conversion for C++ complex numbers to Python complex.
// Include pybind11/complex.h for automatic conversions:
// std::complex<float> <-> Python complex
// std::complex<double> <-> Python complexHigher-order function support and functional programming patterns.
// Include pybind11/functional.h for:
// std::function<T> automatic conversion support
// Lambda and function object binding utilitiesnamespace pybind11 {
// Advanced class options
class multiple_inheritance;
class dynamic_attr;
template<typename T> class base;
class trampoline_self_life_support;
// Enumeration support
template<typename Type> class enum_;
// Smart pointer holders
template<typename T> class holder_type;
template<typename T> class smart_holder;
// Python embedding
class scoped_interpreter;
// Code evaluation
enum eval_mode;
// Chrono support (automatically available with pybind11/chrono.h)
template<typename T> struct type_caster<std::chrono::duration<T>>;
template<typename T> struct type_caster<std::chrono::time_point<T>>;
// GIL management
class gil_scoped_acquire;
class gil_scoped_release;
class gil_not_used;
class multiple_interpreters;
// Advanced function options
template<size_t nurse, size_t patient> auto keep_alive;
auto prepend();
auto scope(handle);
// Operator support
struct self_t {};
constexpr self_t self{};
}Install with Tessl CLI
npx tessl i tessl/pypi-pybind11