============================== pybind11 — smart_holder branch ============================== Overview ======== - 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 changing ``py::class_`` to ``py::classh`` in client code. - The ``py::classh`` functionality includes * support for **two-way** Python/C++ conversions for both ``std::unique_ptr`` and ``std::shared_ptr`` **simultaneously**. — In contrast, ``py::class_`` only supports one-way C++-to-Python conversions for ``std::unique_ptr``, or alternatively two-way Python/C++ conversions for ``std::shared_ptr``, which then excludes the one-way C++-to-Python ``std::unique_ptr`` conversions (this manifests itself through undefined runtime behavior). * passing a Python object back to C++ via ``std::unique_ptr``, safely **disowning** the Python object. * safely passing `"trampoline" `_ objects (objects with C++ virtual function overrides implemented in Python) via ``std::unique_ptr`` or ``std::shared_ptr`` back to C++: associated Python objects are automatically kept alive for the lifetime of the smart-pointer. 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. What is fundamentally different? -------------------------------- - Classic pybind11 has the concept of "smart-pointer is holder". Interoperability between smart-pointers is completely missing. For example, with ``py::class_>``, ``return``-ing a ``std::unique_ptr`` 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 both ``std::unique_ptr`` and ``std::shared_ptr``, and how they interoperate. What motivated the development of the smart_holder code? -------------------------------------------------------- - 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.) Installation ============ Currently ``git clone`` is the only option. We do not have released packages. .. code-block:: bash git clone --branch smart_holder https://github.com/pybind/pybind11.git Everything else is exactly identical to using the default (master) branch. Trampolines and std::unique_ptr ------------------------------- 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: .. code-block:: cpp 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. Related links ============= * 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.)