Blame external/pybind11/docs/upgrade.rst

Packit 534379
Upgrade guide
Packit 534379
#############
Packit 534379
Packit 534379
This is a companion guide to the :doc:`changelog`. While the changelog briefly
Packit 534379
lists all of the new features, improvements and bug fixes, this upgrade guide
Packit 534379
focuses only the subset which directly impacts your experience when upgrading
Packit 534379
to a new version. But it goes into more detail. This includes things like
Packit 534379
deprecated APIs and their replacements, build system changes, general code
Packit 534379
modernization and other useful information.
Packit 534379
Packit 534379
Packit 534379
v2.2
Packit 534379
====
Packit 534379
Packit 534379
Deprecation of the ``PYBIND11_PLUGIN`` macro
Packit 534379
--------------------------------------------
Packit 534379
Packit 534379
``PYBIND11_MODULE`` is now the preferred way to create module entry points.
Packit 534379
The old macro emits a compile-time deprecation warning.
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    // old
Packit 534379
    PYBIND11_PLUGIN(example) {
Packit 534379
        py::module m("example", "documentation string");
Packit 534379
Packit 534379
        m.def("add", [](int a, int b) { return a + b; });
Packit 534379
Packit 534379
        return m.ptr();
Packit 534379
    }
Packit 534379
Packit 534379
    // new
Packit 534379
    PYBIND11_MODULE(example, m) {
Packit 534379
        m.doc() = "documentation string"; // optional
Packit 534379
Packit 534379
        m.def("add", [](int a, int b) { return a + b; });
Packit 534379
    }
Packit 534379
Packit 534379
Packit 534379
New API for defining custom constructors and pickling functions
Packit 534379
---------------------------------------------------------------
Packit 534379
Packit 534379
The old placement-new custom constructors have been deprecated. The new approach
Packit 534379
uses ``py::init()`` and factory functions to greatly improve type safety.
Packit 534379
Packit 534379
Placement-new can be called accidentally with an incompatible type (without any
Packit 534379
compiler errors or warnings), or it can initialize the same object multiple times
Packit 534379
if not careful with the Python-side ``__init__`` calls. The new-style custom
Packit 534379
constructors prevent such mistakes. See :ref:`custom_constructors` for details.
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    // old -- deprecated (runtime warning shown only in debug mode)
Packit 534379
    py::class<Foo>(m, "Foo")
Packit 534379
        .def("__init__", [](Foo &self, ...) {
Packit 534379
            new (&self) Foo(...); // uses placement-new
Packit 534379
        });
Packit 534379
Packit 534379
    // new
Packit 534379
    py::class<Foo>(m, "Foo")
Packit 534379
        .def(py::init([](...) { // Note: no `self` argument
Packit 534379
            return new Foo(...); // return by raw pointer
Packit 534379
            // or: return std::make_unique<Foo>(...); // return by holder
Packit 534379
            // or: return Foo(...); // return by value (move constructor)
Packit 534379
        }));
Packit 534379
Packit 534379
Mirroring the custom constructor changes, ``py::pickle()`` is now the preferred
Packit 534379
way to get and set object state. See :ref:`pickling` for details.
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    // old -- deprecated (runtime warning shown only in debug mode)
Packit 534379
    py::class<Foo>(m, "Foo")
Packit 534379
        ...
Packit 534379
        .def("__getstate__", [](const Foo &self) {
Packit 534379
            return py::make_tuple(self.value1(), self.value2(), ...);
Packit 534379
        })
Packit 534379
        .def("__setstate__", [](Foo &self, py::tuple t) {
Packit 534379
            new (&self) Foo(t[0].cast<std::string>(), ...);
Packit 534379
        });
Packit 534379
Packit 534379
    // new
Packit 534379
    py::class<Foo>(m, "Foo")
Packit 534379
        ...
Packit 534379
        .def(py::pickle(
Packit 534379
            [](const Foo &self) { // __getstate__
Packit 534379
                return py::make_tuple(f.value1(), f.value2(), ...); // unchanged
Packit 534379
            },
Packit 534379
            [](py::tuple t) { // __setstate__, note: no `self` argument
Packit 534379
                return new Foo(t[0].cast<std::string>(), ...);
Packit 534379
                // or: return std::make_unique<Foo>(...); // return by holder
Packit 534379
                // or: return Foo(...); // return by value (move constructor)
Packit 534379
            }
Packit 534379
        ));
Packit 534379
Packit 534379
For both the constructors and pickling, warnings are shown at module
Packit 534379
initialization time (on import, not when the functions are called).
Packit 534379
They're only visible when compiled in debug mode. Sample warning:
Packit 534379
Packit 534379
.. code-block:: none
Packit 534379
Packit 534379
    pybind11-bound class 'mymodule.Foo' is using an old-style placement-new '__init__'
Packit 534379
    which has been deprecated. See the upgrade guide in pybind11's docs.
Packit 534379
Packit 534379
Packit 534379
Stricter enforcement of hidden symbol visibility for pybind11 modules
Packit 534379
---------------------------------------------------------------------
Packit 534379
Packit 534379
pybind11 now tries to actively enforce hidden symbol visibility for modules.
Packit 534379
If you're using either one of pybind11's :doc:`CMake or Python build systems
Packit 534379
<compiling>` (the two example repositories) and you haven't been exporting any
Packit 534379
symbols, there's nothing to be concerned about. All the changes have been done
Packit 534379
transparently in the background. If you were building manually or relied on
Packit 534379
specific default visibility, read on.
Packit 534379
Packit 534379
Setting default symbol visibility to *hidden* has always been recommended for
Packit 534379
pybind11 (see :ref:`faq:symhidden`). On Linux and macOS, hidden symbol
Packit 534379
visibility (in conjunction with the ``strip`` utility) yields much smaller
Packit 534379
module binaries. `CPython's extension docs`_ also recommend hiding symbols
Packit 534379
by default, with the goal of avoiding symbol name clashes between modules.
Packit 534379
Starting with v2.2, pybind11 enforces this more strictly: (1) by declaring
Packit 534379
all symbols inside the ``pybind11`` namespace as hidden and (2) by including
Packit 534379
the ``-fvisibility=hidden`` flag on Linux and macOS (only for extension
Packit 534379
modules, not for embedding the interpreter).
Packit 534379
Packit 534379
.. _CPython's extension docs: https://docs.python.org/3/extending/extending.html#providing-a-c-api-for-an-extension-module
Packit 534379
Packit 534379
The namespace-scope hidden visibility is done automatically in pybind11's
Packit 534379
headers and it's generally transparent to users. It ensures that:
Packit 534379
Packit 534379
* Modules compiled with different pybind11 versions don't clash with each other.
Packit 534379
Packit 534379
* Some new features, like ``py::module_local`` bindings, can work as intended.
Packit 534379
Packit 534379
The ``-fvisibility=hidden`` flag applies the same visibility to user bindings
Packit 534379
outside of the ``pybind11`` namespace. It's now set automatic by pybind11's
Packit 534379
CMake and Python build systems, but this needs to be done manually by users
Packit 534379
of other build systems. Adding this flag:
Packit 534379
Packit 534379
* Minimizes the chances of symbol conflicts between modules. E.g. if two
Packit 534379
  unrelated modules were statically linked to different (ABI-incompatible)
Packit 534379
  versions of the same third-party library, a symbol clash would be likely
Packit 534379
  (and would end with unpredictable results).
Packit 534379
Packit 534379
* Produces smaller binaries on Linux and macOS, as pointed out previously.
Packit 534379
Packit 534379
Within pybind11's CMake build system, ``pybind11_add_module`` has always been
Packit 534379
setting the ``-fvisibility=hidden`` flag in release mode. From now on, it's
Packit 534379
being applied unconditionally, even in debug mode and it can no longer be opted
Packit 534379
out of with the ``NO_EXTRAS`` option. The ``pybind11::module`` target now also
Packit 534379
adds this flag to it's interface. The ``pybind11::embed`` target is unchanged.
Packit 534379
Packit 534379
The most significant change here is for the ``pybind11::module`` target. If you
Packit 534379
were previously relying on default visibility, i.e. if your Python module was
Packit 534379
doubling as a shared library with dependents, you'll need to either export
Packit 534379
symbols manually (recommended for cross-platform libraries) or factor out the
Packit 534379
shared library (and have the Python module link to it like the other
Packit 534379
dependents). As a temporary workaround, you can also restore default visibility
Packit 534379
using the CMake code below, but this is not recommended in the long run:
Packit 534379
Packit 534379
.. code-block:: cmake
Packit 534379
Packit 534379
    target_link_libraries(mymodule PRIVATE pybind11::module)
Packit 534379
Packit 534379
    add_library(restore_default_visibility INTERFACE)
Packit 534379
    target_compile_options(restore_default_visibility INTERFACE -fvisibility=default)
Packit 534379
    target_link_libraries(mymodule PRIVATE restore_default_visibility)
Packit 534379
Packit 534379
Packit 534379
Local STL container bindings
Packit 534379
----------------------------
Packit 534379
Packit 534379
Previous pybind11 versions could only bind types globally -- all pybind11
Packit 534379
modules, even unrelated ones, would have access to the same exported types.
Packit 534379
However, this would also result in a conflict if two modules exported the
Packit 534379
same C++ type, which is especially problematic for very common types, e.g.
Packit 534379
``std::vector<int>``. :ref:`module_local` were added to resolve this (see
Packit 534379
that section for a complete usage guide).
Packit 534379
Packit 534379
``py::class_`` still defaults to global bindings (because these types are
Packit 534379
usually unique across modules), however in order to avoid clashes of opaque
Packit 534379
types, ``py::bind_vector`` and ``py::bind_map`` will now bind STL containers
Packit 534379
as ``py::module_local`` if their elements are: builtins (``int``, ``float``,
Packit 534379
etc.), not bound using ``py::class_``, or bound as ``py::module_local``. For
Packit 534379
example, this change allows multiple modules to bind ``std::vector<int>``
Packit 534379
without causing conflicts. See :ref:`stl_bind` for more details.
Packit 534379
Packit 534379
When upgrading to this version, if you have multiple modules which depend on
Packit 534379
a single global binding of an STL container, note that all modules can still
Packit 534379
accept foreign  ``py::module_local`` types in the direction of Python-to-C++.
Packit 534379
The locality only affects the C++-to-Python direction. If this is needed in
Packit 534379
multiple modules, you'll need to either:
Packit 534379
Packit 534379
* Add a copy of the same STL binding to all of the modules which need it.
Packit 534379
Packit 534379
* Restore the global status of that single binding by marking it
Packit 534379
  ``py::module_local(false)``.
Packit 534379
Packit 534379
The latter is an easy workaround, but in the long run it would be best to
Packit 534379
localize all common type bindings in order to avoid conflicts with
Packit 534379
third-party modules.
Packit 534379
Packit 534379
Packit 534379
Negative strides for Python buffer objects and numpy arrays
Packit 534379
-----------------------------------------------------------
Packit 534379
Packit 534379
Support for negative strides required changing the integer type from unsigned
Packit 534379
to signed in the interfaces of ``py::buffer_info`` and ``py::array``. If you
Packit 534379
have compiler warnings enabled, you may notice some new conversion warnings
Packit 534379
after upgrading. These can be resolved using ``static_cast``.
Packit 534379
Packit 534379
Packit 534379
Deprecation of some ``py::object`` APIs
Packit 534379
---------------------------------------
Packit 534379
Packit 534379
To compare ``py::object`` instances by pointer, you should now use
Packit 534379
``obj1.is(obj2)`` which is equivalent to ``obj1 is obj2`` in Python.
Packit 534379
Previously, pybind11 used ``operator==`` for this (``obj1 == obj2``), but
Packit 534379
that could be confusing and is now deprecated (so that it can eventually
Packit 534379
be replaced with proper rich object comparison in a future release).
Packit 534379
Packit 534379
For classes which inherit from ``py::object``, ``borrowed`` and ``stolen``
Packit 534379
were previously available as protected constructor tags. Now the types
Packit 534379
should be used directly instead: ``borrowed_t{}`` and ``stolen_t{}``
Packit 534379
(`#771 <https://github.com/pybind/pybind11/pull/771>`_).
Packit 534379
Packit 534379
Packit 534379
Stricter compile-time error checking
Packit 534379
------------------------------------
Packit 534379
Packit 534379
Some error checks have been moved from run time to compile time. Notably,
Packit 534379
automatic conversion of ``std::shared_ptr<T>`` is not possible when ``T`` is
Packit 534379
not directly registered with ``py::class_<T>`` (e.g. ``std::shared_ptr<int>``
Packit 534379
or ``std::shared_ptr<std::vector<T>>`` are not automatically convertible).
Packit 534379
Attempting to bind a function with such arguments now results in a compile-time
Packit 534379
error instead of waiting to fail at run time.
Packit 534379
Packit 534379
``py::init<...>()`` constructor definitions are also stricter and now prevent
Packit 534379
bindings which could cause unexpected behavior:
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    struct Example {
Packit 534379
        Example(int &);
Packit 534379
    };
Packit 534379
Packit 534379
    py::class_<Example>(m, "Example")
Packit 534379
        .def(py::init<int &>()); // OK, exact match
Packit 534379
        // .def(py::init<int>()); // compile-time error, mismatch
Packit 534379
Packit 534379
A non-``const`` lvalue reference is not allowed to bind to an rvalue. However,
Packit 534379
note that a constructor taking ``const T &`` can still be registered using
Packit 534379
``py::init<T>()`` because a ``const`` lvalue reference can bind to an rvalue.
Packit 534379
Packit 534379
v2.1
Packit 534379
====
Packit 534379
Packit 534379
Minimum compiler versions are enforced at compile time
Packit 534379
------------------------------------------------------
Packit 534379
Packit 534379
The minimums also apply to v2.0 but the check is now explicit and a compile-time
Packit 534379
error is raised if the compiler does not meet the requirements:
Packit 534379
Packit 534379
* GCC >= 4.8
Packit 534379
* clang >= 3.3 (appleclang >= 5.0)
Packit 534379
* MSVC >= 2015u3
Packit 534379
* Intel C++ >= 15.0
Packit 534379
Packit 534379
Packit 534379
The ``py::metaclass`` attribute is not required for static properties
Packit 534379
---------------------------------------------------------------------
Packit 534379
Packit 534379
Binding classes with static properties is now possible by default. The
Packit 534379
zero-parameter version of ``py::metaclass()`` is deprecated. However, a new
Packit 534379
one-parameter ``py::metaclass(python_type)`` version was added for rare
Packit 534379
cases when a custom metaclass is needed to override pybind11's default.
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    // old -- emits a deprecation warning
Packit 534379
    py::class_<Foo>(m, "Foo", py::metaclass())
Packit 534379
        .def_property_readonly_static("foo", ...);
Packit 534379
Packit 534379
    // new -- static properties work without the attribute
Packit 534379
    py::class_<Foo>(m, "Foo")
Packit 534379
        .def_property_readonly_static("foo", ...);
Packit 534379
Packit 534379
    // new -- advanced feature, override pybind11's default metaclass
Packit 534379
    py::class_<Bar>(m, "Bar", py::metaclass(custom_python_type))
Packit 534379
        ...
Packit 534379
Packit 534379
Packit 534379
v2.0
Packit 534379
====
Packit 534379
Packit 534379
Breaking changes in ``py::class_``
Packit 534379
----------------------------------
Packit 534379
Packit 534379
These changes were necessary to make type definitions in pybind11
Packit 534379
future-proof, to support PyPy via its ``cpyext`` mechanism (`#527
Packit 534379
<https://github.com/pybind/pybind11/pull/527>`_), and to improve efficiency
Packit 534379
(`rev. 86d825 <https://github.com/pybind/pybind11/commit/86d825>`_).
Packit 534379
Packit 534379
1. Declarations of types that provide access via the buffer protocol must
Packit 534379
   now include the ``py::buffer_protocol()`` annotation as an argument to
Packit 534379
   the ``py::class_`` constructor.
Packit 534379
Packit 534379
   .. code-block:: cpp
Packit 534379
Packit 534379
       py::class_<Matrix>("Matrix", py::buffer_protocol())
Packit 534379
           .def(py::init<...>())
Packit 534379
           .def_buffer(...);
Packit 534379
Packit 534379
2. Classes which include static properties (e.g. ``def_readwrite_static()``)
Packit 534379
   must now include the ``py::metaclass()`` attribute. Note: this requirement
Packit 534379
   has since been removed in v2.1. If you're upgrading from 1.x, it's
Packit 534379
   recommended to skip directly to v2.1 or newer.
Packit 534379
Packit 534379
3. This version of pybind11 uses a redesigned mechanism for instantiating
Packit 534379
   trampoline classes that are used to override virtual methods from within
Packit 534379
   Python. This led to the following user-visible syntax change:
Packit 534379
Packit 534379
   .. code-block:: cpp
Packit 534379
Packit 534379
       // old v1.x syntax
Packit 534379
       py::class_<TrampolineClass>("MyClass")
Packit 534379
           .alias<MyClass>()
Packit 534379
           ...
Packit 534379
Packit 534379
       // new v2.x syntax
Packit 534379
       py::class_<MyClass, TrampolineClass>("MyClass")
Packit 534379
           ...
Packit 534379
Packit 534379
   Importantly, both the original and the trampoline class are now specified
Packit 534379
   as arguments to the ``py::class_`` template, and the ``alias<..>()`` call
Packit 534379
   is gone. The new scheme has zero overhead in cases when Python doesn't
Packit 534379
   override any functions of the underlying C++ class.
Packit 534379
   `rev. 86d825 <https://github.com/pybind/pybind11/commit/86d825>`_.
Packit 534379
Packit 534379
   The class type must be the first template argument given to ``py::class_``
Packit 534379
   while the trampoline can be mixed in arbitrary order with other arguments
Packit 534379
   (see the following section).
Packit 534379
Packit 534379
Packit 534379
Deprecation of the ``py::base<T>()`` attribute
Packit 534379
----------------------------------------------
Packit 534379
Packit 534379
``py::base<T>()`` was deprecated in favor of specifying ``T`` as a template
Packit 534379
argument to ``py::class_``. This new syntax also supports multiple inheritance.
Packit 534379
Note that, while the type being exported must be the first argument in the
Packit 534379
``py::class_<Class, ...>`` template, the order of the following types (bases,
Packit 534379
holder and/or trampoline) is not important.
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    // old v1.x
Packit 534379
    py::class_<Derived>("Derived", py::base<Base>());
Packit 534379
Packit 534379
    // new v2.x
Packit 534379
    py::class_<Derived, Base>("Derived");
Packit 534379
Packit 534379
    // new -- multiple inheritance
Packit 534379
    py::class_<Derived, Base1, Base2>("Derived");
Packit 534379
Packit 534379
    // new -- apart from `Derived` the argument order can be arbitrary
Packit 534379
    py::class_<Derived, Base1, Holder, Base2, Trampoline>("Derived");
Packit 534379
Packit 534379
Packit 534379
Out-of-the-box support for ``std::shared_ptr``
Packit 534379
----------------------------------------------
Packit 534379
Packit 534379
The relevant type caster is now built in, so it's no longer necessary to
Packit 534379
include a declaration of the form:
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)
Packit 534379
Packit 534379
Continuing to do so won’t cause an error or even a deprecation warning,
Packit 534379
but it's completely redundant.
Packit 534379
Packit 534379
Packit 534379
Deprecation of a few ``py::object`` APIs
Packit 534379
----------------------------------------
Packit 534379
Packit 534379
All of the old-style calls emit deprecation warnings.
Packit 534379
Packit 534379
+---------------------------------------+---------------------------------------------+
Packit 534379
|  Old syntax                           |  New syntax                                 |
Packit 534379
+=======================================+=============================================+
Packit 534379
| ``obj.call(args...)``                 | ``obj(args...)``                            |
Packit 534379
+---------------------------------------+---------------------------------------------+
Packit 534379
| ``obj.str()``                         | ``py::str(obj)``                            |
Packit 534379
+---------------------------------------+---------------------------------------------+
Packit 534379
| ``auto l = py::list(obj); l.check()`` | ``py::isinstance<py::list>(obj)``           |
Packit 534379
+---------------------------------------+---------------------------------------------+
Packit 534379
| ``py::object(ptr, true)``             | ``py::reinterpret_borrow<py::object>(ptr)`` |
Packit 534379
+---------------------------------------+---------------------------------------------+
Packit 534379
| ``py::object(ptr, false)``            | ``py::reinterpret_steal<py::object>(ptr)``  |
Packit 534379
+---------------------------------------+---------------------------------------------+
Packit 534379
| ``if (obj.attr("foo"))``              | ``if (py::hasattr(obj, "foo"))``            |
Packit 534379
+---------------------------------------+---------------------------------------------+
Packit 534379
| ``if (obj["bar"])``                   | ``if (obj.contains("bar"))``                |
Packit 534379
+---------------------------------------+---------------------------------------------+