diff options
author | Bobby R. Bruce <bbruce@ucdavis.edu> | 2019-09-23 13:52:58 -0700 |
---|---|---|
committer | Bobby R. Bruce <bbruce@ucdavis.edu> | 2019-09-24 21:40:15 +0000 |
commit | f97cf54db7a6f7642cc9fd122f23c4396c39bcf0 (patch) | |
tree | 17d2ed22a1114cb138500d46afddb3bafcc2b418 /ext/pybind11/docs/advanced | |
parent | 9235ae56c282d5a02ada3ed9b4e0fe2ee5738bde (diff) | |
download | gem5-f97cf54db7a6f7642cc9fd122f23c4396c39bcf0.tar.xz |
ext: Updated Pybind11 to version 2.4.1.
This updates Pybind11 from version 2.2.1 to version 2.4.1. This fixes
warning/error received when "<experiment/optional>" is used when
compiling using c++14 with clang. It should be noted that
"ext/pybind11/include/pybind11/std.h" has been changed to include a fix
added by commit ba42457254cc362eddc099f22b60d469cc6369e0. This is
necessary to avoid build errors.
Built: Linux (gcc, c++11) and MacOS (clang, c++14).
Tested: Ran quick tests for X86, ARM, and RISC-V.
Deprecates: https://gem5-review.googlesource.com/c/public/gem5/+/21019
Change-Id: Ie9783511cb6be50136076a55330e645f4f36d075
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21119
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'ext/pybind11/docs/advanced')
-rw-r--r-- | ext/pybind11/docs/advanced/cast/chrono.rst | 2 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/eigen.rst | 18 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/overview.rst | 2 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/stl.rst | 5 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/strings.rst | 4 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/classes.rst | 165 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/exceptions.rst | 80 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/functions.rst | 15 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/misc.rst | 50 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/pycpp/numpy.rst | 26 |
10 files changed, 278 insertions, 89 deletions
diff --git a/ext/pybind11/docs/advanced/cast/chrono.rst b/ext/pybind11/docs/advanced/cast/chrono.rst index 8c6b3d7e5..fbd46057a 100644 --- a/ext/pybind11/docs/advanced/cast/chrono.rst +++ b/ext/pybind11/docs/advanced/cast/chrono.rst @@ -59,7 +59,7 @@ Provided conversions .. rubric:: Python to C++ -- ``datetime.datetime`` → ``std::chrono::system_clock::time_point`` +- ``datetime.datetime`` or ``datetime.date`` or ``datetime.time`` → ``std::chrono::system_clock::time_point`` Date/time objects are converted into system clock timepoints. Any timezone information is ignored and the type is treated as a naive object. diff --git a/ext/pybind11/docs/advanced/cast/eigen.rst b/ext/pybind11/docs/advanced/cast/eigen.rst index acdb51de6..59ba08c3c 100644 --- a/ext/pybind11/docs/advanced/cast/eigen.rst +++ b/ext/pybind11/docs/advanced/cast/eigen.rst @@ -37,11 +37,11 @@ that maps into the source ``numpy.ndarray`` data: this requires both that the data types are the same (e.g. ``dtype='float64'`` and ``MatrixType::Scalar`` is ``double``); and that the storage is layout compatible. The latter limitation is discussed in detail in the section below, and requires careful -consideration: by default, numpy matrices and eigen matrices are *not* storage +consideration: by default, numpy matrices and Eigen matrices are *not* storage compatible. If the numpy matrix cannot be used as is (either because its types differ, e.g. -passing an array of integers to an Eigen paramater requiring doubles, or +passing an array of integers to an Eigen parameter requiring doubles, or because the storage is incompatible), pybind11 makes a temporary copy and passes the copy instead. @@ -89,7 +89,7 @@ as dictated by the binding function's return value policy (see the documentation on :ref:`return_value_policies` for full details). That means, without an explicit return value policy, lvalue references will be copied and pointers will be managed by pybind11. In order to avoid copying, you should -explictly specify an appropriate return value policy, as in the following +explicitly specify an appropriate return value policy, as in the following example: .. code-block:: cpp @@ -226,7 +226,7 @@ order. Failing rather than copying =========================== -The default behaviour when binding ``Eigen::Ref<const MatrixType>`` eigen +The default behaviour when binding ``Eigen::Ref<const MatrixType>`` Eigen references is to copy matrix values when passed a numpy array that does not conform to the element type of ``MatrixType`` or does not have a compatible stride layout. If you want to explicitly avoid copying in such a case, you @@ -275,7 +275,7 @@ Vectors versus column/row matrices Eigen and numpy have fundamentally different notions of a vector. In Eigen, a vector is simply a matrix with the number of columns or rows set to 1 at compile time (for a column vector or row vector, respectively). Numpy, in -contast, has comparable 2-dimensional 1xN and Nx1 arrays, but *also* has +contrast, has comparable 2-dimensional 1xN and Nx1 arrays, but *also* has 1-dimensional arrays of size N. When passing a 2-dimensional 1xN or Nx1 array to Eigen, the Eigen type must @@ -287,15 +287,15 @@ On the other hand, pybind11 allows you to pass 1-dimensional arrays of length N as Eigen parameters. If the Eigen type can hold a column vector of length N it will be passed as such a column vector. If not, but the Eigen type constraints will accept a row vector, it will be passed as a row vector. (The column -vector takes precendence when both are supported, for example, when passing a +vector takes precedence when both are supported, for example, when passing a 1D numpy array to a MatrixXd argument). Note that the type need not be -expicitly a vector: it is permitted to pass a 1D numpy array of size 5 to an +explicitly a vector: it is permitted to pass a 1D numpy array of size 5 to an Eigen ``Matrix<double, Dynamic, 5>``: you would end up with a 1x5 Eigen matrix. Passing the same to an ``Eigen::MatrixXd`` would result in a 5x1 Eigen matrix. -When returning an eigen vector to numpy, the conversion is ambiguous: a row +When returning an Eigen vector to numpy, the conversion is ambiguous: a row vector of length 4 could be returned as either a 1D array of length 4, or as a -2D array of size 1x4. When encoutering such a situation, pybind11 compromises +2D array of size 1x4. When encountering such a situation, pybind11 compromises by considering the returned Eigen type: if it is a compile-time vector--that is, the type has either the number of rows or columns set to 1 at compile time--pybind11 converts to a 1D numpy array when returning the value. For diff --git a/ext/pybind11/docs/advanced/cast/overview.rst b/ext/pybind11/docs/advanced/cast/overview.rst index 2ac7d3009..b0e32a52f 100644 --- a/ext/pybind11/docs/advanced/cast/overview.rst +++ b/ext/pybind11/docs/advanced/cast/overview.rst @@ -131,6 +131,8 @@ as arguments and return values, refer to the section on binding :ref:`classes`. +------------------------------------+---------------------------+-------------------------------+ | ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` | +------------------------------------+---------------------------+-------------------------------+ +| ``std::deque<T>`` | STL double-ended queue | :file:`pybind11/stl.h` | ++------------------------------------+---------------------------+-------------------------------+ | ``std::valarray<T>`` | STL value array | :file:`pybind11/stl.h` | +------------------------------------+---------------------------+-------------------------------+ | ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` | diff --git a/ext/pybind11/docs/advanced/cast/stl.rst b/ext/pybind11/docs/advanced/cast/stl.rst index 3f30c0290..e48409f02 100644 --- a/ext/pybind11/docs/advanced/cast/stl.rst +++ b/ext/pybind11/docs/advanced/cast/stl.rst @@ -5,7 +5,7 @@ Automatic conversion ==================== When including the additional header file :file:`pybind11/stl.h`, conversions -between ``std::vector<>``/``std::list<>``/``std::array<>``, +between ``std::vector<>``/``std::deque<>``/``std::list<>``/``std::array<>``, ``std::set<>``/``std::unordered_set<>``, and ``std::map<>``/``std::unordered_map<>`` and the Python ``list``, ``set`` and ``dict`` data structures are automatically enabled. The types ``std::pair<>`` @@ -175,9 +175,6 @@ in Python, and to define a set of available operations, e.g.: }, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */ // .... -Please take a look at the :ref:`macro_notes` before using the -``PYBIND11_MAKE_OPAQUE`` macro. - .. seealso:: The file :file:`tests/test_opaque_types.cpp` contains a complete diff --git a/ext/pybind11/docs/advanced/cast/strings.rst b/ext/pybind11/docs/advanced/cast/strings.rst index 2cdbade3a..e25701eca 100644 --- a/ext/pybind11/docs/advanced/cast/strings.rst +++ b/ext/pybind11/docs/advanced/cast/strings.rst @@ -58,7 +58,9 @@ Passing bytes to C++ -------------------- A Python ``bytes`` object will be passed to C++ functions that accept -``std::string`` or ``char*`` *without* conversion. +``std::string`` or ``char*`` *without* conversion. On Python 3, in order to +make a function *only* accept ``bytes`` (and not ``str``), declare it as taking +a ``py::bytes`` argument. Returning C++ strings to Python diff --git a/ext/pybind11/docs/advanced/classes.rst b/ext/pybind11/docs/advanced/classes.rst index 93deeec62..ae5907dee 100644 --- a/ext/pybind11/docs/advanced/classes.rst +++ b/ext/pybind11/docs/advanced/classes.rst @@ -46,11 +46,10 @@ Normally, the binding code for these classes would look as follows: .. code-block:: cpp PYBIND11_MODULE(example, m) { - py::class_<Animal> animal(m, "Animal"); - animal + py::class_<Animal>(m, "Animal") .def("go", &Animal::go); - py::class_<Dog>(m, "Dog", animal) + py::class_<Dog, Animal>(m, "Dog") .def(py::init<>()); m.def("call_go", &call_go); @@ -81,10 +80,10 @@ helper class that is defined as follows: } }; -The macro :func:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual -functions, and :func:`PYBIND11_OVERLOAD` should be used for functions which have -a default implementation. There are also two alternate macros -:func:`PYBIND11_OVERLOAD_PURE_NAME` and :func:`PYBIND11_OVERLOAD_NAME` which +The macro :c:macro:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual +functions, and :c:macro:`PYBIND11_OVERLOAD` should be used for functions which have +a default implementation. There are also two alternate macros +:c:macro:`PYBIND11_OVERLOAD_PURE_NAME` and :c:macro:`PYBIND11_OVERLOAD_NAME` which take a string-valued name argument between the *Parent class* and *Name of the function* slots, which defines the name of function in Python. This is required when the C++ and Python versions of the @@ -93,15 +92,14 @@ function have different names, e.g. ``operator()`` vs ``__call__``. The binding code also needs a few minor adaptations (highlighted): .. code-block:: cpp - :emphasize-lines: 2,4,5 + :emphasize-lines: 2,3 PYBIND11_MODULE(example, m) { - py::class_<Animal, PyAnimal /* <--- trampoline*/> animal(m, "Animal"); - animal + py::class_<Animal, PyAnimal /* <--- trampoline*/>(m, "Animal") .def(py::init<>()) .def("go", &Animal::go); - py::class_<Dog>(m, "Dog", animal) + py::class_<Dog, Animal>(m, "Dog") .def(py::init<>()); m.def("call_go", &call_go); @@ -116,11 +114,11 @@ define a constructor as usual. Bindings should be made against the actual class, not the trampoline helper class. .. code-block:: cpp + :emphasize-lines: 3 - py::class_<Animal, PyAnimal /* <--- trampoline*/> animal(m, "Animal"); - animal - .def(py::init<>()) - .def("go", &PyAnimal::go); /* <--- THIS IS WRONG, use &Animal::go */ + py::class_<Animal, PyAnimal /* <--- trampoline*/>(m, "Animal"); + .def(py::init<>()) + .def("go", &PyAnimal::go); /* <--- THIS IS WRONG, use &Animal::go */ Note, however, that the above is sufficient for allowing python classes to extend ``Animal``, but not ``Dog``: see :ref:`virtual_and_inheritance` for the @@ -155,9 +153,9 @@ Here is an example: .. code-block:: python - class Dachschund(Dog): + class Dachshund(Dog): def __init__(self, name): - Dog.__init__(self) # Without this, undefind behavior may occur if the C++ portions are referenced. + Dog.__init__(self) # Without this, undefined behavior may occur if the C++ portions are referenced. self.name = name def bark(self): return "yap!" @@ -241,7 +239,7 @@ override the ``name()`` method): class PyDog : public Dog { public: using Dog::Dog; // Inherit constructors - std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Dog, go, n_times); } + std::string go(int n_times) override { PYBIND11_OVERLOAD(std::string, Dog, go, n_times); } std::string name() override { PYBIND11_OVERLOAD(std::string, Dog, name, ); } std::string bark() override { PYBIND11_OVERLOAD(std::string, Dog, bark, ); } }; @@ -327,6 +325,10 @@ can now create a python class that inherits from ``Dog``: Extended trampoline class functionality ======================================= +.. _extended_class_functionality_forced_trampoline: + +Forced trampoline class initialisation +-------------------------------------- The trampoline classes described in the previous sections are, by default, only initialized when needed. More specifically, they are initialized when a python class actually inherits from a registered type (instead of merely creating an @@ -354,6 +356,45 @@ ensuring member initialization and (eventual) destruction. See the file :file:`tests/test_virtual_functions.cpp` for complete examples showing both normal and forced trampoline instantiation. +Different method signatures +--------------------------- +The macro's introduced in :ref:`overriding_virtuals` cover most of the standard +use cases when exposing C++ classes to Python. Sometimes it is hard or unwieldy +to create a direct one-on-one mapping between the arguments and method return +type. + +An example would be when the C++ signature contains output arguments using +references (See also :ref:`faq_reference_arguments`). Another way of solving +this is to use the method body of the trampoline class to do conversions to the +input and return of the Python method. + +The main building block to do so is the :func:`get_overload`, this function +allows retrieving a method implemented in Python from within the trampoline's +methods. Consider for example a C++ method which has the signature +``bool myMethod(int32_t& value)``, where the return indicates whether +something should be done with the ``value``. This can be made convenient on the +Python side by allowing the Python function to return ``None`` or an ``int``: + +.. code-block:: cpp + + bool MyClass::myMethod(int32_t& value) + { + pybind11::gil_scoped_acquire gil; // Acquire the GIL while in this scope. + // Try to look up the overloaded method on the Python side. + pybind11::function overload = pybind11::get_overload(this, "myMethod"); + if (overload) { // method is found + auto obj = overload(value); // Call the Python function. + if (py::isinstance<py::int_>(obj)) { // check if it returned a Python integer type + value = obj.cast<int32_t>(); // Cast it and assign it to the value. + return true; // Return true; value should be used. + } else { + return false; // Python returned none, return false. + } + } + return false; // Alternatively return MyClass::myMethod(value); + } + + .. _custom_constructors: Custom constructors @@ -621,6 +662,7 @@ to Python. .def(py::self *= float()) .def(float() * py::self) .def(py::self * float()) + .def(-py::self) .def("__repr__", &Vector2::toString); } @@ -760,7 +802,7 @@ document)---pybind11 will automatically find out which is which. The only requirement is that the first template argument is the type to be declared. 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. +as well as inheriting from multiple Python and/or pybind11-exported classes. There is one caveat regarding the implementation of this feature: @@ -781,7 +823,7 @@ are listed. Module-local class bindings =========================== -When creating a binding for a class, pybind by default makes that binding +When creating a binding for a class, pybind11 by default makes that binding "global" across modules. What this means is that a type defined in one module can be returned from any module resulting in the same Python type. For example, this allows the following: @@ -999,3 +1041,86 @@ described trampoline: requires a more explicit function binding in the form of ``.def("foo", static_cast<int (A::*)() const>(&Publicist::foo));`` where ``int (A::*)() const`` is the type of ``A::foo``. + +Custom automatic downcasters +============================ + +As explained in :ref:`inheritance`, pybind11 comes with built-in +understanding of the dynamic type of polymorphic objects in C++; that +is, returning a Pet to Python produces a Python object that knows it's +wrapping a Dog, if Pet has virtual methods and pybind11 knows about +Dog and this Pet is in fact a Dog. Sometimes, you might want to +provide this automatic downcasting behavior when creating bindings for +a class hierarchy that does not use standard C++ polymorphism, such as +LLVM [#f4]_. As long as there's some way to determine at runtime +whether a downcast is safe, you can proceed by specializing the +``pybind11::polymorphic_type_hook`` template: + +.. code-block:: cpp + + enum class PetKind { Cat, Dog, Zebra }; + struct Pet { // Not polymorphic: has no virtual methods + const PetKind kind; + int age = 0; + protected: + Pet(PetKind _kind) : kind(_kind) {} + }; + struct Dog : Pet { + Dog() : Pet(PetKind::Dog) {} + std::string sound = "woof!"; + std::string bark() const { return sound; } + }; + + namespace pybind11 { + template<> struct polymorphic_type_hook<Pet> { + static const void *get(const Pet *src, const std::type_info*& type) { + // note that src may be nullptr + if (src && src->kind == PetKind::Dog) { + type = &typeid(Dog); + return static_cast<const Dog*>(src); + } + return src; + } + }; + } // namespace pybind11 + +When pybind11 wants to convert a C++ pointer of type ``Base*`` to a +Python object, it calls ``polymorphic_type_hook<Base>::get()`` to +determine if a downcast is possible. The ``get()`` function should use +whatever runtime information is available to determine if its ``src`` +parameter is in fact an instance of some class ``Derived`` that +inherits from ``Base``. If it finds such a ``Derived``, it sets ``type += &typeid(Derived)`` and returns a pointer to the ``Derived`` object +that contains ``src``. Otherwise, it just returns ``src``, leaving +``type`` at its default value of nullptr. If you set ``type`` to a +type that pybind11 doesn't know about, no downcasting will occur, and +the original ``src`` pointer will be used with its static type +``Base*``. + +It is critical that the returned pointer and ``type`` argument of +``get()`` agree with each other: if ``type`` is set to something +non-null, the returned pointer must point to the start of an object +whose type is ``type``. If the hierarchy being exposed uses only +single inheritance, a simple ``return src;`` will achieve this just +fine, but in the general case, you must cast ``src`` to the +appropriate derived-class pointer (e.g. using +``static_cast<Derived>(src)``) before allowing it to be returned as a +``void*``. + +.. [#f4] https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html + +.. note:: + + pybind11's standard support for downcasting objects whose types + have virtual methods is implemented using + ``polymorphic_type_hook`` too, using the standard C++ ability to + determine the most-derived type of a polymorphic object using + ``typeid()`` and to cast a base pointer to that most-derived type + (even if you don't know what it is) using ``dynamic_cast<void*>``. + +.. seealso:: + + The file :file:`tests/test_tagbased_polymorphic.cpp` contains a + more complete example, including a demonstration of how to provide + automatic downcasting for an entire class hierarchy without + writing one get() function for each class. diff --git a/ext/pybind11/docs/advanced/exceptions.rst b/ext/pybind11/docs/advanced/exceptions.rst index 348337916..75ac24ae9 100644 --- a/ext/pybind11/docs/advanced/exceptions.rst +++ b/ext/pybind11/docs/advanced/exceptions.rst @@ -11,45 +11,45 @@ exceptions: .. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}| -+--------------------------------------+------------------------------+ -| C++ exception type | Python exception type | -+======================================+==============================+ -| :class:`std::exception` | ``RuntimeError`` | -+--------------------------------------+------------------------------+ -| :class:`std::bad_alloc` | ``MemoryError`` | -+--------------------------------------+------------------------------+ -| :class:`std::domain_error` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::invalid_argument` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::length_error` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::out_of_range` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::range_error` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`pybind11::stop_iteration` | ``StopIteration`` (used to | -| | implement custom iterators) | -+--------------------------------------+------------------------------+ -| :class:`pybind11::index_error` | ``IndexError`` (used to | -| | indicate out of bounds | -| | accesses in ``__getitem__``, | -| | ``__setitem__``, etc.) | -+--------------------------------------+------------------------------+ -| :class:`pybind11::value_error` | ``ValueError`` (used to | -| | indicate wrong value passed | -| | in ``container.remove(...)`` | -+--------------------------------------+------------------------------+ -| :class:`pybind11::key_error` | ``KeyError`` (used to | -| | indicate out of bounds | -| | accesses in ``__getitem__``, | -| | ``__setitem__`` in dict-like | -| | objects, etc.) | -+--------------------------------------+------------------------------+ -| :class:`pybind11::error_already_set` | Indicates that the Python | -| | exception flag has already | -| | been initialized | -+--------------------------------------+------------------------------+ ++--------------------------------------+--------------------------------------+ +| C++ exception type | Python exception type | ++======================================+======================================+ +| :class:`std::exception` | ``RuntimeError`` | ++--------------------------------------+--------------------------------------+ +| :class:`std::bad_alloc` | ``MemoryError`` | ++--------------------------------------+--------------------------------------+ +| :class:`std::domain_error` | ``ValueError`` | ++--------------------------------------+--------------------------------------+ +| :class:`std::invalid_argument` | ``ValueError`` | ++--------------------------------------+--------------------------------------+ +| :class:`std::length_error` | ``ValueError`` | ++--------------------------------------+--------------------------------------+ +| :class:`std::out_of_range` | ``IndexError`` | ++--------------------------------------+--------------------------------------+ +| :class:`std::range_error` | ``ValueError`` | ++--------------------------------------+--------------------------------------+ +| :class:`pybind11::stop_iteration` | ``StopIteration`` (used to implement | +| | custom iterators) | ++--------------------------------------+--------------------------------------+ +| :class:`pybind11::index_error` | ``IndexError`` (used to indicate out | +| | of bounds access in ``__getitem__``, | +| | ``__setitem__``, etc.) | ++--------------------------------------+--------------------------------------+ +| :class:`pybind11::value_error` | ``ValueError`` (used to indicate | +| | wrong value passed in | +| | ``container.remove(...)``) | ++--------------------------------------+--------------------------------------+ +| :class:`pybind11::key_error` | ``KeyError`` (used to indicate out | +| | of bounds access in ``__getitem__``, | +| | ``__setitem__`` in dict-like | +| | objects, etc.) | ++--------------------------------------+--------------------------------------+ +| :class:`pybind11::error_already_set` | Indicates that the Python exception | +| | flag has already been set via Python | +| | API calls from C++ code; this C++ | +| | exception is used to propagate such | +| | a Python exception back to Python. | ++--------------------------------------+--------------------------------------+ When a Python function invoked from C++ throws an exception, it is converted into a C++ exception of type :class:`error_already_set` whose string payload @@ -138,5 +138,5 @@ section. error return without exception set``. Exceptions that you do not plan to handle should simply not be caught, or - may be explicity (re-)thrown to delegate it to the other, + may be explicitly (re-)thrown to delegate it to the other, previously-declared existing exception translators. diff --git a/ext/pybind11/docs/advanced/functions.rst b/ext/pybind11/docs/advanced/functions.rst index c7892b5d3..3e1a3ff0e 100644 --- a/ext/pybind11/docs/advanced/functions.rst +++ b/ext/pybind11/docs/advanced/functions.rst @@ -126,7 +126,7 @@ targeted arguments can be passed through the :class:`cpp_function` constructor: .. warning:: - Code with invalid return value policies might access unitialized memory or + Code with invalid return value policies might access uninitialized memory or free data structures multiple times, which can lead to hard-to-debug non-determinism and segmentation faults, hence it is worth spending the time to understand all the different options in the table above. @@ -438,7 +438,7 @@ To explicitly enable or disable this behaviour, using the py::class_<Cat>(m, "Cat").def(py::init<>()); m.def("bark", [](Dog *dog) -> std::string { if (dog) return "woof!"; /* Called with a Dog instance */ - else return "(no dog)"; /* Called with None, d == nullptr */ + else return "(no dog)"; /* Called with None, dog == nullptr */ }, py::arg("dog").none(true)); m.def("meow", [](Cat *cat) -> std::string { // Can't be called with None argument @@ -467,13 +467,22 @@ dog)"``, while attempting to call ``meow(None)`` will raise a ``TypeError``: The default behaviour when the tag is unspecified is to allow ``None``. +.. note:: + + Even when ``.none(true)`` is specified for an argument, ``None`` will be converted to a + ``nullptr`` *only* for custom and :ref:`opaque <opaque>` types. Pointers to built-in types + (``double *``, ``int *``, ...) and STL types (``std::vector<T> *``, ...; if ``pybind11/stl.h`` + is included) are copied when converted to C++ (see :doc:`/advanced/cast/overview`) and will + not allow ``None`` as argument. To pass optional argument of these copied types consider + using ``std::optional<T>`` + Overload resolution order ========================= When a function or method with multiple overloads is called from Python, pybind11 determines which overload to call in two passes. The first pass attempts to call each overload without allowing argument conversion (as if -every argument had been specified as ``py::arg().noconvert()`` as decribed +every argument had been specified as ``py::arg().noconvert()`` as described above). If no overload succeeds in the no-conversion first pass, a second pass is diff --git a/ext/pybind11/docs/advanced/misc.rst b/ext/pybind11/docs/advanced/misc.rst index 87481ba32..5b38ec759 100644 --- a/ext/pybind11/docs/advanced/misc.rst +++ b/ext/pybind11/docs/advanced/misc.rst @@ -7,13 +7,32 @@ General notes regarding convenience macros ========================================== pybind11 provides a few convenience macros such as -:func:`PYBIND11_MAKE_OPAQUE` and :func:`PYBIND11_DECLARE_HOLDER_TYPE`, and -``PYBIND11_OVERLOAD_*``. Since these are "just" macros that are evaluated -in the preprocessor (which has no concept of types), they *will* get confused -by commas in a template argument such as ``PYBIND11_OVERLOAD(MyReturnValue<T1, -T2>, myFunc)``. In this case, the preprocessor assumes that the comma indicates -the beginning of the next parameter. Use a ``typedef`` to bind the template to -another name and use it in the macro to avoid this problem. +:func:`PYBIND11_DECLARE_HOLDER_TYPE` and ``PYBIND11_OVERLOAD_*``. Since these +are "just" macros that are evaluated in the preprocessor (which has no concept +of types), they *will* get confused by commas in a template argument; for +example, consider: + +.. code-block:: cpp + + PYBIND11_OVERLOAD(MyReturnType<T1, T2>, Class<T3, T4>, func) + +The limitation of the C preprocessor interprets this as five arguments (with new +arguments beginning after each comma) rather than three. To get around this, +there are two alternatives: you can use a type alias, or you can wrap the type +using the ``PYBIND11_TYPE`` macro: + +.. code-block:: cpp + + // Version 1: using a type alias + using ReturnType = MyReturnType<T1, T2>; + using ClassType = Class<T3, T4>; + PYBIND11_OVERLOAD(ReturnType, ClassType, func); + + // Version 2: using the PYBIND11_TYPE macro: + PYBIND11_OVERLOAD(PYBIND11_TYPE(MyReturnType<T1, T2>), + PYBIND11_TYPE(Class<T3, T4>), func) + +The ``PYBIND11_MAKE_OPAQUE`` macro does *not* require the above workarounds. .. _gil: @@ -137,7 +156,7 @@ Naturally, both methods will fail when there are cyclic dependencies. Note that pybind11 code compiled with hidden-by-default symbol visibility (e.g. via the command line flag ``-fvisibility=hidden`` on GCC/Clang), which is -required proper pybind11 functionality, can interfere with the ability to +required for proper pybind11 functionality, can interfere with the ability to access types defined in another extension module. Working around this requires manually exporting types that are accessed by multiple extension modules; pybind11 provides a macro to do just this: @@ -216,6 +235,21 @@ avoids this issue involves weak reference with a cleanup callback: // Create a weak reference with a cleanup callback and initially leak it (void) py::weakref(m.attr("BaseClass"), cleanup_callback).release(); +.. note:: + + PyPy (at least version 5.9) does not garbage collect objects when the + interpreter exits. An alternative approach (which also works on CPython) is to use + the :py:mod:`atexit` module [#f7]_, for example: + + .. code-block:: cpp + + auto atexit = py::module::import("atexit"); + atexit.attr("register")(py::cpp_function([]() { + // perform cleanup here -- this function is called with the GIL held + })); + + .. [#f7] https://docs.python.org/3/library/atexit.html + Generating documentation using Sphinx ===================================== diff --git a/ext/pybind11/docs/advanced/pycpp/numpy.rst b/ext/pybind11/docs/advanced/pycpp/numpy.rst index 98b0c25b9..458f99e97 100644 --- a/ext/pybind11/docs/advanced/pycpp/numpy.rst +++ b/ext/pybind11/docs/advanced/pycpp/numpy.rst @@ -41,7 +41,7 @@ completely avoid copy operations with Python expressions like py::format_descriptor<float>::format(), /* Python struct-style format descriptor */ 2, /* Number of dimensions */ { m.rows(), m.cols() }, /* Buffer dimensions */ - { sizeof(float) * m.rows(), /* Strides (in bytes) for each index */ + { sizeof(float) * m.cols(), /* Strides (in bytes) for each index */ sizeof(float) } ); }); @@ -261,7 +261,7 @@ simply using ``vectorize``). namespace py = pybind11; py::array_t<double> add_arrays(py::array_t<double> input1, py::array_t<double> input2) { - auto buf1 = input1.request(), buf2 = input2.request(); + py::buffer_info buf1 = input1.request(), buf2 = input2.request(); if (buf1.ndim != 1 || buf2.ndim != 1) throw std::runtime_error("Number of dimensions must be one"); @@ -272,7 +272,7 @@ simply using ``vectorize``). /* No pointer is passed, so NumPy will allocate the buffer */ auto result = py::array_t<double>(buf1.size); - auto buf3 = result.request(); + py::buffer_info buf3 = result.request(); double *ptr1 = (double *) buf1.ptr, *ptr2 = (double *) buf2.ptr, @@ -364,3 +364,23 @@ uses of ``py::array``: The file :file:`tests/test_numpy_array.cpp` contains additional examples demonstrating the use of this feature. + +Ellipsis +======== + +Python 3 provides a convenient ``...`` ellipsis notation that is often used to +slice multidimensional arrays. For instance, the following snippet extracts the +middle dimensions of a tensor with the first and last index set to zero. + +.. code-block:: python + + a = # a NumPy array + b = a[0, ..., 0] + +The function ``py::ellipsis()`` function can be used to perform the same +operation on the C++ side: + +.. code-block:: cpp + + py::array a = /* A NumPy array */; + py::array b = a[py::make_tuple(0, py::ellipsis(), 0)]; |