mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-13 09:03:54 +00:00
2097826346
Problem ======= The template trampoline pattern documented in PR #322 has a problem with virtual method overloads in intermediate classes in the inheritance chain between the trampoline class and the base class. For example, consider the following inheritance structure, where `B` is the actual class, `PyB<B>` is the trampoline class, and `PyA<B>` is an intermediate class adding A's methods into the trampoline: PyB<B> -> PyA<B> -> B -> A Suppose PyA<B> has a method `some_method()` with a PYBIND11_OVERLOAD in it to overload the virtual `A::some_method()`. If a Python class `C` is defined that inherits from the pybind11-registered `B` and tries to provide an overriding `some_method()`, the PYBIND11_OVERLOADs declared in PyA<B> fails to find this overloaded method, and thus never invoke it (or, if pure virtual and not overridden in PyB<B>, raises an exception). This happens because the base (internal) `PYBIND11_OVERLOAD_INT` macro simply calls `get_overload(this, name)`; `get_overload()` then uses the inferred type of `this` to do a type lookup in `registered_types_cpp`. This is where it fails: `this` will be a `PyA<B> *`, but `PyA<B>` is neither the base type (`B`) nor the trampoline type (`PyB<B>`). As a result, the overload fails and we get a failed overload lookup. The fix ======= The fix is relatively simple: we can cast `this` passed to `get_overload()` to a `const B *`, which lets get_overload look up the correct class. Since trampoline classes should be derived from `B` classes anyway, this cast should be perfectly safe. This does require adding the class name as an argument to the PYBIND11_OVERLOAD_INT macro, but leaves the public macro signatures unchanged. |
||
---|---|---|
.. | ||
CMakeLists.txt | ||
conftest.py | ||
constructor_stats.h | ||
object.h | ||
pybind11_tests.cpp | ||
pybind11_tests.h | ||
test_buffers.cpp | ||
test_buffers.py | ||
test_callbacks.cpp | ||
test_callbacks.py | ||
test_constants_and_functions.cpp | ||
test_constants_and_functions.py | ||
test_eigen.cpp | ||
test_eigen.py | ||
test_enum.cpp | ||
test_enum.py | ||
test_eval_call.py | ||
test_eval.cpp | ||
test_eval.py | ||
test_exceptions.cpp | ||
test_exceptions.py | ||
test_inheritance.cpp | ||
test_inheritance.py | ||
test_issues.cpp | ||
test_issues.py | ||
test_keep_alive.cpp | ||
test_keep_alive.py | ||
test_kwargs_and_defaults.cpp | ||
test_kwargs_and_defaults.py | ||
test_methods_and_attributes.cpp | ||
test_methods_and_attributes.py | ||
test_modules.cpp | ||
test_modules.py | ||
test_numpy_dtypes.cpp | ||
test_numpy_dtypes.py | ||
test_numpy_vectorize.cpp | ||
test_numpy_vectorize.py | ||
test_opaque_types.cpp | ||
test_opaque_types.py | ||
test_operator_overloading.cpp | ||
test_operator_overloading.py | ||
test_pickling.cpp | ||
test_pickling.py | ||
test_python_types.cpp | ||
test_python_types.py | ||
test_sequences_and_iterators.cpp | ||
test_sequences_and_iterators.py | ||
test_smart_ptr.cpp | ||
test_smart_ptr.py | ||
test_stl_binders.cpp | ||
test_stl_binders.py | ||
test_virtual_functions.cpp | ||
test_virtual_functions.py |