- The smart_holder branch is a strict superset of the pybind11 master branch. Everything that works with the master branch is expected to work exactly the same with the smart_holder branch.
- Activating the smart_holder functionality for a given C++ type
T
is as easy as changingpy::class_<T>
topy::classh<T>
in client code. - The
py::classh<T>
functionality includes- support for two-way Python/C++ conversions for both
std::unique_ptr<T>
andstd::shared_ptr<T>
simultaneously. — In contrast,py::class_<T>
only supports one-way C++-to-Python conversions forstd::unique_ptr<T>
, or alternatively two-way Python/C++ conversions forstd::shared_ptr<T>
, which then excludes the one-way C++-to-Pythonstd::unique_ptr<T>
conversions (this manifests itself through undefined runtime behavior). - passing a Python object back to C++ via
std::unique_ptr<T>
, safely disowning the Python object. - safely passing "trampoline"
objects (objects with C++ virtual function overrides implemented in
Python) via
std::unique_ptr<T>
orstd::shared_ptr<T>
back to C++: associated Python objects are automatically kept alive for the lifetime of the smart-pointer.
- support for two-way Python/C++ conversions for both
Note: As of PR #5257
the smart_holder functionality is fully baked into pybind11.
Prior to PR #5257 the smart_holder implementation was an "add-on", which made
it necessary to use a PYBIND11_SMART_HOLDER_TYPE_CASTERS
macro. This macro
still exists for backward compatibility, but is now a no-op. The trade-off
for this convenience is that the PYBIND11_INTERNALS_VERSION
needed to be
changed. Consequently, Python extension modules built with the smart_holder
branch no longer interoperate with extension modules built with the pybind11
master branch. If cross-extension-module interoperability is required, all
extension modules involved must be built with the smart_holder branch.
— Probably, most extension modules do not require cross-extension-module
interoperability, but exceptions to this are quite common.
- Classic pybind11 has the concept of "smart-pointer is holder".
Interoperability between smart-pointers is completely missing. For example,
with
py::class_<T, std::shared_ptr<T>>
,return
-ing astd::unique_ptr<T>
leads to undefined runtime behavior (#1138). A systematic analysis can be found here. py::smart_holder
has a richer concept in comparison, with well-defined runtime behavior in all situations.py::smart_holder
"knows" about bothstd::unique_ptr<T>
andstd::shared_ptr<T>
, and how they interoperate.
- The original context was retooling of PyCLIF, to use pybind11 underneath, instead of directly targeting the Python C API. Essentially the smart_holder branch is porting established PyCLIF functionality into pybind11. (However, this work also led to bug fixes in PyCLIF.)
Currently git clone
is the only option. We do not have released packages.
git clone --branch smart_holder https://github.com/pybind/pybind11.git
Everything else is exactly identical to using the default (master) branch.
A pybind11 "trampoline"
is a C++ helper class with virtual function overrides that transparently
call back from C++ into Python. To enable safely passing a std::unique_ptr
to a trampoline object between Python and C++, the trampoline class must
inherit from py::trampoline_self_life_support
, for example:
class PyAnimal : public Animal, public py::trampoline_self_life_support {
...
};
This is the only difference compared to classic pybind11. A fairly minimal but complete example is tests/test_class_sh_trampoline_unique_ptr.cpp.
- The smart_holder branch addresses issue #1138 and the ten issues enumerated in the description of PR 2839.
- Description of PR #2672, from which the smart_holder branch was created.
- Small slide deck presented in meeting with pybind11 maintainers on Feb 22, 2021. Slides 5 and 6 show performance comparisons. (These are outdated but probably not far off.)