Skip to content

Python multiple inheritance #693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 16 additions & 24 deletions docs/advanced/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -619,27 +619,19 @@ interspersed with alias types and holder types (discussed earlier in this
document)---pybind11 will automatically find out which is which. The only
requirement is that the first template argument is the type to be declared.

There are two caveats regarding the implementation of this feature:

1. When only one base type is specified for a C++ type that actually has
multiple bases, pybind11 will assume that it does not participate in
multiple inheritance, which can lead to undefined behavior. In such cases,
add the tag ``multiple_inheritance``:

.. code-block:: cpp

py::class_<MyType, BaseType2>(m, "MyType", py::multiple_inheritance());

The tag is redundant and does not need to be specified when multiple base
types are listed.

2. As was previously discussed in the section on :ref:`overriding_virtuals`, it
is easy to create Python types that derive from C++ classes. It is even
possible to make use of multiple inheritance to declare a Python class which
has e.g. a C++ and a Python class as bases. However, any attempt to create a
type that has *two or more* C++ classes in its hierarchy of base types will
fail with a fatal error message: ``TypeError: multiple bases have instance
lay-out conflict``. Core Python types that are implemented in C (e.g.
``dict``, ``list``, ``Exception``, etc.) also fall under this combination
and cannot be combined with C++ types bound using pybind11 via multiple
inheritance.
It is also permitted to inherit multiply from exported C++ classes in Python,
as well as inheriting from multiple Python and/or pybind-exported classes.

There is one caveat regarding the implementation of this feature:

When only one base type is specified for a C++ type that actually has multiple
bases, pybind11 will assume that it does not participate in multiple
inheritance, which can lead to undefined behavior. In such cases, add the tag
``multiple_inheritance`` to the class constructor:

.. code-block:: cpp

py::class_<MyType, BaseType2>(m, "MyType", py::multiple_inheritance());

The tag is redundant and does not need to be specified when multiple base types
are listed.
8 changes: 4 additions & 4 deletions include/pybind11/attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,17 +210,17 @@ struct type_record {
/// How large is the underlying C++ type?
size_t type_size = 0;

/// How large is pybind11::instance<type>?
size_t instance_size = 0;
/// How large is the type's holder?
size_t holder_size = 0;

/// The global operator new can be overridden with a class-specific variant
void *(*operator_new)(size_t) = ::operator new;

/// Function pointer to class_<..>::init_holder
void (*init_holder)(PyObject *, const void *) = nullptr;
void (*init_holder)(instance *, const void *) = nullptr;

/// Function pointer to class_<..>::dealloc
void (*dealloc)(PyObject *) = nullptr;
void (*dealloc)(const detail::value_and_holder &) = nullptr;

/// List of base classes of the newly created type
list bases;
Expand Down
Loading