@@ -85,6 +85,34 @@ inline PyTypeObject *make_static_property_type() {
85
85
86
86
#endif // PYPY
87
87
88
+ /* * Inheriting from multiple C++ types in Python is not supported -- set an error instead.
89
+ A Python definition (`class C(A, B): pass`) will call `tp_new` so we check for multiple
90
+ C++ bases here. On the other hand, C++ type definitions (`py::class_<C, A, B>(m, "C")`)
91
+ don't not use `tp_new` and will not trigger this error. */
92
+ extern " C" inline PyObject *pybind11_meta_new (PyTypeObject *metaclass, PyObject *args,
93
+ PyObject *kwargs) {
94
+ PyObject *bases = PyTuple_GetItem (args, 1 ); // arguments: (name, bases, dict)
95
+ if (!bases)
96
+ return nullptr ;
97
+
98
+ auto &internals = get_internals ();
99
+ auto num_cpp_bases = 0 ;
100
+ for (auto base : reinterpret_borrow<tuple>(bases)) {
101
+ auto base_type = (PyTypeObject *) base.ptr ();
102
+ auto instance_size = static_cast <size_t >(base_type->tp_basicsize );
103
+ if (PyObject_IsSubclass (base.ptr (), internals.get_base (instance_size)))
104
+ ++num_cpp_bases;
105
+ }
106
+
107
+ if (num_cpp_bases > 1 ) {
108
+ PyErr_SetString (PyExc_TypeError, " Can't inherit from multiple C++ classes in Python."
109
+ " Use py::class_ to define the class in C++ instead." );
110
+ return nullptr ;
111
+ } else {
112
+ return PyType_Type.tp_new (metaclass, args, kwargs);
113
+ }
114
+ }
115
+
88
116
/* * Types with static properties need to handle `Type.static_prop = x` in a specific way.
89
117
By default, Python replaces the `static_property` itself, but for wrapped C++ types
90
118
we need to call `static_property.__set__()` in order to propagate the new value to
@@ -135,6 +163,8 @@ inline PyTypeObject* make_default_metaclass() {
135
163
type->tp_name = name;
136
164
type->tp_base = &PyType_Type;
137
165
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
166
+
167
+ type->tp_new = pybind11_meta_new;
138
168
type->tp_setattro = pybind11_meta_setattro;
139
169
140
170
if (PyType_Ready (type) < 0 )
@@ -145,7 +175,7 @@ inline PyTypeObject* make_default_metaclass() {
145
175
146
176
// / Instance creation function for all pybind11 types. It only allocates space for the
147
177
// / C++ object, but doesn't call the constructor -- an `__init__` function must do that.
148
- extern " C" inline PyObject *pybind11_new (PyTypeObject *type, PyObject *, PyObject *) {
178
+ extern " C" inline PyObject *pybind11_object_new (PyTypeObject *type, PyObject *, PyObject *) {
149
179
PyObject *self = type->tp_alloc (type, 0 );
150
180
auto instance = (instance_essentials<void > *) self;
151
181
auto tinfo = get_type_info (type);
@@ -159,7 +189,7 @@ extern "C" inline PyObject *pybind11_new(PyTypeObject *type, PyObject *, PyObjec
159
189
// / An `__init__` function constructs the C++ object. Users should provide at least one
160
190
// / of these using `py::init` or directly with `.def(__init__, ...)`. Otherwise, the
161
191
// / following default function will be used which simply throws an exception.
162
- extern " C" inline int pybind11_init (PyObject *self, PyObject *, PyObject *) {
192
+ extern " C" inline int pybind11_object_init (PyObject *self, PyObject *, PyObject *) {
163
193
PyTypeObject *type = Py_TYPE (self);
164
194
std::string msg;
165
195
#if defined(PYPY_VERSION)
@@ -173,7 +203,7 @@ extern "C" inline int pybind11_init(PyObject *self, PyObject *, PyObject *) {
173
203
174
204
// / Instance destructor function for all pybind11 types. It calls `type_info.dealloc`
175
205
// / to destroy the C++ object itself, while the rest is Python bookkeeping.
176
- extern " C" inline void pybind11_dealloc (PyObject *self) {
206
+ extern " C" inline void pybind11_object_dealloc (PyObject *self) {
177
207
auto instance = (instance_essentials<void > *) self;
178
208
if (instance->value ) {
179
209
auto type = Py_TYPE (self);
@@ -190,7 +220,7 @@ extern "C" inline void pybind11_dealloc(PyObject *self) {
190
220
}
191
221
}
192
222
if (!found)
193
- pybind11_fail (" pybind11_dealloc (): Tried to deallocate unregistered instance!" );
223
+ pybind11_fail (" pybind11_object_dealloc (): Tried to deallocate unregistered instance!" );
194
224
195
225
if (instance->weakrefs )
196
226
PyObject_ClearWeakRefs (self);
@@ -230,9 +260,9 @@ inline PyObject *make_object_base_type(size_t instance_size) {
230
260
type->tp_basicsize = static_cast <ssize_t >(instance_size);
231
261
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
232
262
233
- type->tp_new = pybind11_new ;
234
- type->tp_init = pybind11_init ;
235
- type->tp_dealloc = pybind11_dealloc ;
263
+ type->tp_new = pybind11_object_new ;
264
+ type->tp_init = pybind11_object_init ;
265
+ type->tp_dealloc = pybind11_object_dealloc ;
236
266
237
267
/* Support weak references (needed for the keep_alive feature) */
238
268
type->tp_weaklistoffset = offsetof (instance_essentials<void >, weakrefs);
@@ -429,7 +459,7 @@ inline PyObject* make_new_python_type(const type_record &rec) {
429
459
type->tp_bases = bases.release ().ptr ();
430
460
431
461
/* Don't inherit base __init__ */
432
- type->tp_init = pybind11_init ;
462
+ type->tp_init = pybind11_object_init ;
433
463
434
464
/* Supported protocols */
435
465
type->tp_as_number = &heap_type->as_number ;
0 commit comments