0
# Advanced Features
1
2
pybind11 provides advanced features for complex binding scenarios including inheritance, virtual methods, operators, enumerations, smart pointer integration, and embedding Python in C++ applications.
3
4
## Capabilities
5
6
### Inheritance and Virtual Methods
7
8
Support for C++ inheritance hierarchies and virtual method overriding from Python.
9
10
```cpp { .api }
11
// Virtual method overriding support
12
#define PYBIND11_OVERRIDE(ret_type, cname, fn, ...) \
13
PYBIND11_OVERRIDE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, __VA_ARGS__)
14
15
#define PYBIND11_OVERRIDE_PURE(ret_type, cname, fn, ...) \
16
PYBIND11_OVERRIDE_PURE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, __VA_ARGS__)
17
18
// Trampoline class base for smart holder compatibility
19
class trampoline_self_life_support {
20
// Base class for trampoline classes when using smart_holder
21
};
22
23
// Multiple inheritance support
24
class multiple_inheritance {
25
// Template parameter to enable multiple inheritance
26
};
27
28
// Dynamic attribute support
29
class dynamic_attr {
30
// Template parameter to enable dynamic attribute access
31
};
32
```
33
34
### Operator Binding
35
36
Comprehensive support for C++ operator overloading in Python.
37
38
```cpp { .api }
39
// Arithmetic operators
40
auto operator+(const T& a, const T& b);
41
auto operator-(const T& a, const T& b);
42
auto operator*(const T& a, const T& b);
43
auto operator/(const T& a, const T& b);
44
auto operator%(const T& a, const T& b);
45
46
// Comparison operators
47
auto operator==(const T& a, const T& b);
48
auto operator!=(const T& a, const T& b);
49
auto operator<(const T& a, const T& b);
50
auto operator<=(const T& a, const T& b);
51
auto operator>(const T& a, const T& b);
52
auto operator>=(const T& a, const T& b);
53
54
// Unary operators
55
auto operator-(const T& a); // Negation
56
auto operator+(const T& a); // Unary plus
57
auto operator!(const T& a); // Logical not
58
auto operator~(const T& a); // Bitwise not
59
60
// Compound assignment
61
auto operator+=(T& a, const T& b);
62
auto operator-=(T& a, const T& b);
63
auto operator*=(T& a, const T& b);
64
auto operator/=(T& a, const T& b);
65
66
// Stream operators
67
auto operator<<(std::ostream& os, const T& obj);
68
auto operator>>(std::istream& is, T& obj);
69
70
// Subscript operator
71
auto operator[](T& obj, const Key& key);
72
73
// Call operator
74
auto operator()(T& obj, Args... args);
75
76
// Self operators (using 'self' placeholder)
77
py::self + py::self;
78
py::self - py::self;
79
py::self * py::self;
80
py::self / py::self;
81
py::self == py::self;
82
py::self != py::self;
83
py::self < py::self;
84
```
85
86
### Enumeration Binding
87
88
Support for C++ enumerations with various options.
89
90
```cpp { .api }
91
template<typename Type>
92
class enum_ : public class_<Type> {
93
public:
94
// Constructor
95
enum_(const handle &scope, const char *name);
96
97
// Add enum values
98
enum_ &value(const char *name, Type value, const char *doc = nullptr);
99
100
// Export values to enclosing scope
101
enum_ &export_values();
102
103
// Arithmetic operations on enums (optional)
104
enum_ &def_arithmetic();
105
};
106
107
// Scoped enums (enum class)
108
template<typename Type>
109
enum_<Type> bind_enum(module_ &m, const char *name);
110
```
111
112
### Smart Pointer Integration
113
114
Advanced smart pointer support and lifetime management.
115
116
```cpp { .api }
117
// Smart pointer holders
118
template<typename T>
119
class holder_type<std::unique_ptr<T>>;
120
121
template<typename T>
122
class holder_type<std::shared_ptr<T>>;
123
124
// Smart holder (experimental advanced holder)
125
template<typename T>
126
class smart_holder;
127
128
// Holder type specification in class binding
129
py::class_<MyClass, std::shared_ptr<MyClass>>(m, "MyClass");
130
py::class_<MyClass, std::unique_ptr<MyClass>>(m, "MyClass");
131
132
// Return value policies for smart pointers
133
return_value_policy::take_ownership; // Transfer unique_ptr ownership
134
return_value_policy::copy; // Copy shared_ptr
135
return_value_policy::reference_internal; // Keep parent alive
136
```
137
138
### Python Embedding
139
140
Embed Python interpreter in C++ applications.
141
142
```cpp { .api }
143
// Python interpreter management
144
class scoped_interpreter {
145
public:
146
scoped_interpreter(bool init_signal_handlers = true,
147
int argc = 0, const char * const *argv = nullptr,
148
bool add_program_dir_to_path = true);
149
~scoped_interpreter();
150
151
// Non-copyable, non-movable
152
scoped_interpreter(const scoped_interpreter&) = delete;
153
scoped_interpreter& operator=(const scoped_interpreter&) = delete;
154
};
155
156
// Manual interpreter control
157
void initialize_interpreter(bool init_signal_handlers = true,
158
int argc = 0, const char * const *argv = nullptr,
159
bool add_program_dir_to_path = true);
160
161
void finalize_interpreter();
162
163
bool is_interpreter_running();
164
165
// Code execution
166
object exec(const str &expr, object global = globals(), object local = object());
167
object exec(const char *expr, object global = globals(), object local = object());
168
169
object eval(const str &expr, object global = globals(), object local = object());
170
object eval(const char *expr, object global = globals(), object local = object());
171
172
template<typename... Args>
173
object eval_file(const str &fname, Args &&...args);
174
```
175
176
### Function Attributes and Policies
177
178
Advanced function binding options and call policies.
179
180
```cpp { .api }
181
// Function naming and documentation
182
auto name(const char *name);
183
auto doc(const char *doc);
184
185
// Argument handling
186
auto arg(const char *name);
187
template<typename T>
188
auto arg_v(const char *name, T &&value, const char *doc = nullptr);
189
190
// Call policies and lifetime management
191
auto keep_alive(size_t nurse, size_t patient);
192
auto keep_alive_impl(size_t nurse, size_t patient);
193
194
// Function relationship
195
auto sibling(handle other_function);
196
auto is_method(handle self);
197
auto is_operator();
198
199
// Advanced function options
200
auto prepend(); // Prepend to overload chain
201
auto scope(handle scope); // Set function scope
202
```
203
204
### Global Variables and Constants
205
206
Binding global variables and constants to Python.
207
208
```cpp { .api }
209
// Module-level attributes
210
template<typename T>
211
module_ &attr(const char *name, T &&value);
212
213
// Read-only attributes
214
template<typename T>
215
module_ &def_readonly(const char *name, const T *value);
216
217
// Read-write attributes
218
template<typename T>
219
module_ &def_readwrite(const char *name, T *value);
220
```
221
222
### Threading and GIL Management
223
224
Advanced Global Interpreter Lock (GIL) management for multi-threading.
225
226
```cpp { .api }
227
// GIL management classes
228
class gil_scoped_acquire {
229
public:
230
gil_scoped_acquire();
231
~gil_scoped_acquire();
232
233
// Non-copyable, non-movable
234
gil_scoped_acquire(const gil_scoped_acquire&) = delete;
235
};
236
237
class gil_scoped_release {
238
public:
239
gil_scoped_release();
240
~gil_scoped_release();
241
242
// Non-copyable, non-movable
243
gil_scoped_release(const gil_scoped_release&) = delete;
244
};
245
246
// GIL-free function marking
247
class gil_not_used {
248
// Mark module as not using GIL
249
};
250
251
// Multiple interpreter support
252
class multiple_interpreters {
253
// Mark module as supporting multiple interpreters
254
};
255
```
256
257
### Custom Metaclasses and Descriptors
258
259
Advanced class customization options.
260
261
```cpp { .api }
262
// Custom metaclass support
263
template<typename T>
264
class metaclass {
265
public:
266
metaclass(handle meta);
267
};
268
269
// Property descriptors with custom behavior
270
template<typename Getter, typename Setter>
271
class custom_property {
272
public:
273
custom_property(Getter getter, Setter setter);
274
};
275
276
// Dynamic attribute access
277
template<typename T>
278
struct dynamic_attr_support {
279
// Enable __setattr__ and __getattr__
280
};
281
```
282
283
## Usage Examples
284
285
### Inheritance and Virtual Methods
286
287
```cpp
288
#include <pybind11/pybind11.h>
289
290
namespace py = pybind11;
291
292
// Base class with virtual methods
293
class Animal {
294
public:
295
virtual ~Animal() = default;
296
virtual std::string speak() const = 0;
297
virtual std::string type() const { return "Animal"; }
298
};
299
300
// Trampoline class for Python inheritance
301
class PyAnimal : public Animal {
302
public:
303
using Animal::Animal;
304
305
std::string speak() const override {
306
PYBIND11_OVERRIDE_PURE(std::string, Animal, speak);
307
}
308
309
std::string type() const override {
310
PYBIND11_OVERRIDE(std::string, Animal, type);
311
}
312
};
313
314
// Derived class
315
class Dog : public Animal {
316
public:
317
std::string speak() const override { return "Woof!"; }
318
std::string type() const override { return "Dog"; }
319
};
320
321
PYBIND11_MODULE(example, m) {
322
py::class_<Animal, PyAnimal>(m, "Animal")
323
.def(py::init<>())
324
.def("speak", &Animal::speak)
325
.def("type", &Animal::type);
326
327
py::class_<Dog>(m, "Dog", py::base<Animal>())
328
.def(py::init<>());
329
}
330
331
// Python usage:
332
// class Cat(Animal):
333
// def speak(self):
334
// return "Meow!"
335
//
336
// cat = Cat()
337
// print(cat.speak()) # "Meow!"
338
```
339
340
### Operator Overloading
341
342
```cpp
343
#include <pybind11/pybind11.h>
344
#include <pybind11/operators.h>
345
346
namespace py = pybind11;
347
348
class Vector2D {
349
public:
350
double x, y;
351
352
Vector2D(double x = 0, double y = 0) : x(x), y(y) {}
353
354
Vector2D operator+(const Vector2D& other) const {
355
return Vector2D(x + other.x, y + other.y);
356
}
357
358
Vector2D operator-(const Vector2D& other) const {
359
return Vector2D(x - other.x, y - other.y);
360
}
361
362
Vector2D operator*(double scalar) const {
363
return Vector2D(x * scalar, y * scalar);
364
}
365
366
bool operator==(const Vector2D& other) const {
367
return x == other.x && y == other.y;
368
}
369
370
double length() const {
371
return std::sqrt(x * x + y * y);
372
}
373
};
374
375
PYBIND11_MODULE(example, m) {
376
py::class_<Vector2D>(m, "Vector2D")
377
.def(py::init<double, double>())
378
.def_readwrite("x", &Vector2D::x)
379
.def_readwrite("y", &Vector2D::y)
380
.def("length", &Vector2D::length)
381
// Bind operators
382
.def(py::self + py::self)
383
.def(py::self - py::self)
384
.def(py::self * double())
385
.def(double() * py::self)
386
.def(py::self == py::self)
387
.def("__repr__", [](const Vector2D& v) {
388
return "Vector2D(" + std::to_string(v.x) + ", " + std::to_string(v.y) + ")";
389
});
390
}
391
```
392
393
### Enumeration Binding
394
395
```cpp
396
#include <pybind11/pybind11.h>
397
398
namespace py = pybind11;
399
400
enum class Color { Red, Green, Blue };
401
402
enum LogLevel {
403
DEBUG = 0,
404
INFO = 1,
405
WARNING = 2,
406
ERROR = 3
407
};
408
409
PYBIND11_MODULE(example, m) {
410
// Scoped enum (enum class)
411
py::enum_<Color>(m, "Color")
412
.value("Red", Color::Red)
413
.value("Green", Color::Green)
414
.value("Blue", Color::Blue)
415
.export_values(); // Optional: export to module scope
416
417
// Traditional enum with arithmetic operations
418
py::enum_<LogLevel>(m, "LogLevel")
419
.value("DEBUG", DEBUG)
420
.value("INFO", INFO)
421
.value("WARNING", WARNING)
422
.value("ERROR", ERROR)
423
.def_arithmetic(); // Enable arithmetic operations
424
}
425
426
// Python usage:
427
// print(Color.Red) # Color.Red
428
// print(LogLevel.INFO + 1) # 2 (if arithmetic enabled)
429
```
430
431
### Smart Pointer Integration
432
433
```cpp
434
#include <pybind11/pybind11.h>
435
#include <memory>
436
437
namespace py = pybind11;
438
439
class Resource {
440
public:
441
Resource(const std::string& name) : name_(name) {}
442
const std::string& name() const { return name_; }
443
444
private:
445
std::string name_;
446
};
447
448
// Factory function returning unique_ptr
449
std::unique_ptr<Resource> create_resource(const std::string& name) {
450
return std::make_unique<Resource>(name);
451
}
452
453
// Factory function returning shared_ptr
454
std::shared_ptr<Resource> create_shared_resource(const std::string& name) {
455
return std::make_shared<Resource>(name);
456
}
457
458
PYBIND11_MODULE(example, m) {
459
// Bind class with shared_ptr holder
460
py::class_<Resource, std::shared_ptr<Resource>>(m, "Resource")
461
.def(py::init<const std::string&>())
462
.def("name", &Resource::name);
463
464
m.def("create_resource", &create_resource);
465
m.def("create_shared_resource", &create_shared_resource);
466
}
467
```
468
469
### Python Embedding
470
471
```cpp
472
#include <pybind11/pybind11.h>
473
#include <pybind11/embed.h>
474
475
namespace py = pybind11;
476
477
int main() {
478
// Start Python interpreter
479
py::scoped_interpreter guard{};
480
481
// Execute Python code
482
py::exec("print('Hello from embedded Python!')");
483
484
// Execute Python expressions and get results
485
py::object result = py::eval("2 + 3");
486
std::cout << "2 + 3 = " << result.cast<int>() << std::endl;
487
488
// Import and use Python modules
489
py::object math = py::module_::import("math");
490
py::object pi = math.attr("pi");
491
std::cout << "Pi = " << pi.cast<double>() << std::endl;
492
493
// Execute Python file
494
py::eval_file("script.py");
495
496
// Create Python functions from C++
497
py::exec(R"(
498
def fibonacci(n):
499
if n <= 1:
500
return n
501
return fibonacci(n-1) + fibonacci(n-2)
502
)");
503
504
py::object fib = py::globals()["fibonacci"];
505
py::object result_fib = fib(10);
506
std::cout << "Fibonacci(10) = " << result_fib.cast<int>() << std::endl;
507
508
return 0;
509
}
510
```
511
512
### Advanced GIL Management
513
514
```cpp
515
#include <pybind11/pybind11.h>
516
#include <thread>
517
518
namespace py = pybind11;
519
520
void cpu_intensive_work() {
521
// Release GIL for CPU-intensive work
522
py::gil_scoped_release release;
523
524
// Perform CPU-intensive computation
525
for (int i = 0; i < 1000000; ++i) {
526
// Some computation
527
}
528
529
// GIL automatically reacquired when 'release' goes out of scope
530
}
531
532
void call_python_from_thread(py::function callback) {
533
std::thread worker([callback]() {
534
// Acquire GIL in thread
535
py::gil_scoped_acquire acquire;
536
537
try {
538
callback("Hello from thread!");
539
}
540
catch (py::error_already_set& e) {
541
std::cerr << "Python exception in thread: " << e.what() << std::endl;
542
}
543
});
544
545
worker.join();
546
}
547
548
PYBIND11_MODULE(example, m) {
549
m.def("cpu_intensive_work", &cpu_intensive_work);
550
m.def("call_python_from_thread", &call_python_from_thread);
551
}
552
```
553
554
### Dynamic Attributes
555
556
```cpp
557
#include <pybind11/pybind11.h>
558
559
namespace py = pybind11;
560
561
class DynamicClass {
562
public:
563
DynamicClass() = default;
564
565
// Optional: custom attribute access
566
py::object get_attr(const std::string& name) {
567
auto it = attrs_.find(name);
568
if (it != attrs_.end()) {
569
return it->second;
570
}
571
throw py::attribute_error("Attribute '" + name + "' not found");
572
}
573
574
void set_attr(const std::string& name, py::object value) {
575
attrs_[name] = value;
576
}
577
578
private:
579
std::map<std::string, py::object> attrs_;
580
};
581
582
PYBIND11_MODULE(example, m) {
583
py::class_<DynamicClass>(m, "DynamicClass", py::dynamic_attr())
584
.def(py::init<>())
585
.def("get_attr", &DynamicClass::get_attr)
586
.def("set_attr", &DynamicClass::set_attr);
587
}
588
589
// Python usage:
590
// obj = DynamicClass()
591
// obj.new_attribute = "Hello" # Dynamic attribute assignment
592
// print(obj.new_attribute) # "Hello"
593
```
594
595
### Chrono and DateTime Integration
596
597
Automatic conversion between C++ chrono types and Python datetime objects.
598
599
```cpp { .api }
600
// Include pybind11/chrono.h for automatic conversions:
601
// std::chrono::duration<Rep, Period> <-> datetime.timedelta
602
// std::chrono::time_point<Clock, Duration> <-> datetime.datetime
603
604
// Supported chrono types
605
using std::chrono::system_clock;
606
using std::chrono::steady_clock;
607
using std::chrono::high_resolution_clock;
608
using std::chrono::duration;
609
using std::chrono::time_point;
610
611
// Common duration types automatically supported
612
using std::chrono::nanoseconds;
613
using std::chrono::microseconds;
614
using std::chrono::milliseconds;
615
using std::chrono::seconds;
616
using std::chrono::minutes;
617
using std::chrono::hours;
618
```
619
620
### Code Evaluation and Execution
621
622
Execute Python code and evaluate expressions from C++.
623
624
```cpp { .api }
625
// Evaluation modes
626
enum eval_mode {
627
eval_expr, // Evaluate expression, return result
628
eval_single_statement, // Execute single statement, return none
629
eval_statements // Execute multiple statements, return none
630
};
631
632
// Evaluation functions
633
template<eval_mode mode = eval_expr>
634
object eval(const str &expr, object global = globals(), object local = object());
635
636
template<eval_mode mode = eval_expr>
637
object eval(const char *expr, object global = globals(), object local = object());
638
639
// File execution
640
template<eval_mode mode = eval_statements, typename... Args>
641
object eval_file(const str &fname, Args &&...args);
642
```
643
644
### Complex Number Support
645
646
Automatic conversion for C++ complex numbers to Python complex.
647
648
```cpp { .api }
649
// Include pybind11/complex.h for automatic conversions:
650
// std::complex<float> <-> Python complex
651
// std::complex<double> <-> Python complex
652
```
653
654
### Functional Programming Utilities
655
656
Higher-order function support and functional programming patterns.
657
658
```cpp { .api }
659
// Include pybind11/functional.h for:
660
// std::function<T> automatic conversion support
661
// Lambda and function object binding utilities
662
```
663
664
## Types
665
666
```cpp { .api }
667
namespace pybind11 {
668
// Advanced class options
669
class multiple_inheritance;
670
class dynamic_attr;
671
template<typename T> class base;
672
class trampoline_self_life_support;
673
674
// Enumeration support
675
template<typename Type> class enum_;
676
677
// Smart pointer holders
678
template<typename T> class holder_type;
679
template<typename T> class smart_holder;
680
681
// Python embedding
682
class scoped_interpreter;
683
684
// Code evaluation
685
enum eval_mode;
686
687
// Chrono support (automatically available with pybind11/chrono.h)
688
template<typename T> struct type_caster<std::chrono::duration<T>>;
689
template<typename T> struct type_caster<std::chrono::time_point<T>>;
690
691
// GIL management
692
class gil_scoped_acquire;
693
class gil_scoped_release;
694
class gil_not_used;
695
class multiple_interpreters;
696
697
// Advanced function options
698
template<size_t nurse, size_t patient> auto keep_alive;
699
auto prepend();
700
auto scope(handle);
701
702
// Operator support
703
struct self_t {};
704
constexpr self_t self{};
705
}
706
```