CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pybind11

Seamless operability between C++11 and Python for creating Python bindings of existing C++ code

Pending
Overview
Eval results
Files

advanced-features.mddocs/

Advanced Features

pybind11 provides advanced features for complex binding scenarios including inheritance, virtual methods, operators, enumerations, smart pointer integration, and embedding Python in C++ applications.

Capabilities

Inheritance and Virtual Methods

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
};

Operator Binding

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;

Enumeration Binding

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);

Smart Pointer Integration

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 alive

Python Embedding

Embed 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);

Function Attributes and Policies

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 scope

Global Variables and Constants

Binding 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);

Threading and GIL Management

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
};

Custom Metaclasses and Descriptors

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__ 
};

Usage Examples

Inheritance and Virtual Methods

#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!"

Operator Overloading

#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) + ")";
        });
}

Enumeration Binding

#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)

Smart Pointer Integration

#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);
}

Python Embedding

#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;
}

Advanced GIL Management

#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);
}

Dynamic Attributes

#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"

Chrono and DateTime Integration

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;

Code Evaluation and Execution

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);

Complex Number Support

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 complex

Functional Programming Utilities

Higher-order function support and functional programming patterns.

// Include pybind11/functional.h for:
// std::function<T> automatic conversion support
// Lambda and function object binding utilities

Types

namespace 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

docs

advanced-features.md

core-binding.md

exception-handling.md

index.md

numpy-integration.md

python-package.md

stl-integration.md

type-system.md

tile.json