diff options
Diffstat (limited to 'ext/pybind11/docs/advanced/cast')
-rw-r--r-- | ext/pybind11/docs/advanced/cast/custom.rst | 6 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/eigen.rst | 8 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/functional.rst | 6 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/overview.rst | 5 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/stl.rst | 109 | ||||
-rw-r--r-- | ext/pybind11/docs/advanced/cast/strings.rst | 116 |
6 files changed, 202 insertions, 48 deletions
diff --git a/ext/pybind11/docs/advanced/cast/custom.rst b/ext/pybind11/docs/advanced/cast/custom.rst index c854e7fcd..e4f99ac5b 100644 --- a/ext/pybind11/docs/advanced/cast/custom.rst +++ b/ext/pybind11/docs/advanced/cast/custom.rst @@ -78,6 +78,12 @@ type is explicitly allowed. }; }} // namespace pybind11::detail +.. note:: + + A ``type_caster<T>`` defined with ``PYBIND11_TYPE_CASTER(T, ...)`` requires + that ``T`` is default-constructible (``value`` is first default constructed + and then ``load()`` assigns to it). + .. warning:: When using custom type casters, it's important to declare them consistently diff --git a/ext/pybind11/docs/advanced/cast/eigen.rst b/ext/pybind11/docs/advanced/cast/eigen.rst index 5b0b08ca6..acdb51de6 100644 --- a/ext/pybind11/docs/advanced/cast/eigen.rst +++ b/ext/pybind11/docs/advanced/cast/eigen.rst @@ -57,7 +57,7 @@ expected: .. code-block:: cpp - void scale_by_2(Eigen::Ref<Eigen::VectorXd> m) { + void scale_by_2(Eigen::Ref<Eigen::VectorXd> v) { v *= 2; } @@ -252,11 +252,11 @@ copying to take place: using namespace pybind11::literals; // for "arg"_a py::class_<MyClass>(m, "MyClass") // ... other class definitions - .def("some_method", &MyClass::some_method, py::arg().nocopy()); + .def("some_method", &MyClass::some_method, py::arg().noconvert()); m.def("some_function", &some_function, - "big"_a.nocopy(), // <- Don't allow copying for this arg - "small"_a // <- This one can be copied if needed + "big"_a.noconvert(), // <- Don't allow copying for this arg + "small"_a // <- This one can be copied if needed ); With the above binding code, attempting to call the the ``some_method(m)`` diff --git a/ext/pybind11/docs/advanced/cast/functional.rst b/ext/pybind11/docs/advanced/cast/functional.rst index 5d0a01d13..d9b460575 100644 --- a/ext/pybind11/docs/advanced/cast/functional.rst +++ b/ext/pybind11/docs/advanced/cast/functional.rst @@ -56,14 +56,10 @@ trivial to generate binding code for all of these functions. #include <pybind11/functional.h> - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - + PYBIND11_MODULE(example, m) { m.def("func_arg", &func_arg); m.def("func_ret", &func_ret); m.def("func_cpp", &func_cpp); - - return m.ptr(); } The following interactive session shows how to call them from Python. diff --git a/ext/pybind11/docs/advanced/cast/overview.rst b/ext/pybind11/docs/advanced/cast/overview.rst index 54c11a90a..2ac7d3009 100644 --- a/ext/pybind11/docs/advanced/cast/overview.rst +++ b/ext/pybind11/docs/advanced/cast/overview.rst @@ -116,6 +116,9 @@ as arguments and return values, refer to the section on binding :ref:`classes`. +------------------------------------+---------------------------+-------------------------------+ | ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` | +------------------------------------+---------------------------+-------------------------------+ +| ``std::string_view``, | STL C++17 string views | :file:`pybind11/pybind11.h` | +| ``std::u16string_view``, etc. | | | ++------------------------------------+---------------------------+-------------------------------+ | ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` | +------------------------------------+---------------------------+-------------------------------+ | ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` | @@ -144,6 +147,8 @@ as arguments and return values, refer to the section on binding :ref:`classes`. +------------------------------------+---------------------------+-------------------------------+ | ``std::experimental::optional<T>`` | STL optional type (exp.) | :file:`pybind11/stl.h` | +------------------------------------+---------------------------+-------------------------------+ +| ``std::variant<...>`` | Type-safe union (C++17) | :file:`pybind11/stl.h` | ++------------------------------------+---------------------------+-------------------------------+ | ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` | +------------------------------------+---------------------------+-------------------------------+ | ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` | diff --git a/ext/pybind11/docs/advanced/cast/stl.rst b/ext/pybind11/docs/advanced/cast/stl.rst index c76da5ca1..3f30c0290 100644 --- a/ext/pybind11/docs/advanced/cast/stl.rst +++ b/ext/pybind11/docs/advanced/cast/stl.rst @@ -23,9 +23,62 @@ next sections for more details and alternative approaches that avoid this. .. seealso:: - The file :file:`tests/test_python_types.cpp` contains a complete + The file :file:`tests/test_stl.cpp` contains a complete example that demonstrates how to pass STL data types in more detail. +.. _cpp17_container_casters: + +C++17 library containers +======================== + +The :file:`pybind11/stl.h` header also includes support for ``std::optional<>`` +and ``std::variant<>``. These require a C++17 compiler and standard library. +In C++14 mode, ``std::experimental::optional<>`` is supported if available. + +Various versions of these containers also exist for C++11 (e.g. in Boost). +pybind11 provides an easy way to specialize the ``type_caster`` for such +types: + +.. code-block:: cpp + + // `boost::optional` as an example -- can be any `std::optional`-like container + namespace pybind11 { namespace detail { + template <typename T> + struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {}; + }} + +The above should be placed in a header file and included in all translation units +where automatic conversion is needed. Similarly, a specialization can be provided +for custom variant types: + +.. code-block:: cpp + + // `boost::variant` as an example -- can be any `std::variant`-like container + namespace pybind11 { namespace detail { + template <typename... Ts> + struct type_caster<boost::variant<Ts...>> : variant_caster<boost::variant<Ts...>> {}; + + // Specifies the function used to visit the variant -- `apply_visitor` instead of `visit` + template <> + struct visit_helper<boost::variant> { + template <typename... Args> + static auto call(Args &&...args) -> decltype(boost::apply_visitor(args...)) { + return boost::apply_visitor(args...); + } + }; + }} // namespace pybind11::detail + +The ``visit_helper`` specialization is not required if your ``name::variant`` provides +a ``name::visit()`` function. For any other function name, the specialization must be +included to tell pybind11 how to visit the variant. + +.. note:: + + pybind11 only supports the modern implementation of ``boost::variant`` + which makes use of variadic templates. This requires Boost 1.56 or newer. + Additionally, on Windows, MSVC 2017 is required because ``boost::variant`` + falls back to the old non-variadic implementation on MSVC 2015. + .. _opaque: Making opaque types @@ -105,10 +158,10 @@ the declaration before any binding code (e.g. invocations to ``class_::def()``, etc.). This macro must be specified at the top level (and outside of any namespaces), since it instantiates a partial template overload. If your binding code consists of -multiple compilation units, it must be present in every file preceding any -usage of ``std::vector<int>``. Opaque types must also have a corresponding -``class_`` declaration to associate them with a name in Python, and to define a -set of available operations, e.g.: +multiple compilation units, it must be present in every file (typically via a +common header) preceding any usage of ``std::vector<int>``. Opaque types must +also have a corresponding ``class_`` declaration to associate them with a name +in Python, and to define a set of available operations, e.g.: .. code-block:: cpp @@ -122,6 +175,20 @@ 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 + example that demonstrates how to create and expose opaque types using + pybind11 in more detail. + +.. _stl_bind: + +Binding STL containers +====================== + The ability to expose STL containers as native Python objects is a fairly common request, hence pybind11 also provides an optional header file named :file:`pybind11/stl_bind.h` that does exactly this. The mapped containers try @@ -143,14 +210,34 @@ The following example showcases usage of :file:`pybind11/stl_bind.h`: py::bind_vector<std::vector<int>>(m, "VectorInt"); py::bind_map<std::map<std::string, double>>(m, "MapStringDouble"); -Please take a look at the :ref:`macro_notes` before using the -``PYBIND11_MAKE_OPAQUE`` macro. +When binding STL containers pybind11 considers the types of the container's +elements to decide whether the container should be confined to the local module +(via the :ref:`module_local` feature). If the container element types are +anything other than already-bound custom types bound without +``py::module_local()`` the container binding will have ``py::module_local()`` +applied. This includes converting types such as numeric types, strings, Eigen +types; and types that have not yet been bound at the time of the stl container +binding. This module-local binding is designed to avoid potential conflicts +between module bindings (for example, from two separate modules each attempting +to bind ``std::vector<int>`` as a python type). + +It is possible to override this behavior to force a definition to be either +module-local or global. To do so, you can pass the attributes +``py::module_local()`` (to make the binding module-local) or +``py::module_local(false)`` (to make the binding global) into the +``py::bind_vector`` or ``py::bind_map`` arguments: -.. seealso:: +.. code-block:: cpp - The file :file:`tests/test_opaque_types.cpp` contains a complete - example that demonstrates how to create and expose opaque types using - pybind11 in more detail. + py::bind_vector<std::vector<int>>(m, "VectorInt", py::module_local(false)); + +Note, however, that such a global binding would make it impossible to load this +module at the same time as any other pybind module that also attempts to bind +the same container type (``std::vector<int>`` in the above example). + +See :ref:`module_local` for more details on module-local bindings. + +.. seealso:: The file :file:`tests/test_stl_binders.cpp` shows how to use the convenience STL container wrappers. diff --git a/ext/pybind11/docs/advanced/cast/strings.rst b/ext/pybind11/docs/advanced/cast/strings.rst index c70fb0bec..2cdbade3a 100644 --- a/ext/pybind11/docs/advanced/cast/strings.rst +++ b/ext/pybind11/docs/advanced/cast/strings.rst @@ -3,14 +3,23 @@ Strings, bytes and Unicode conversions .. note:: - This section discusses string handling in terms of Python 3 strings. For Python 2.7, replace all occurrences of ``str`` with ``unicode`` and ``bytes`` with ``str``. Python 2.7 users may find it best to use ``from __future__ import unicode_literals`` to avoid unintentionally using ``str`` instead of ``unicode``. + This section discusses string handling in terms of Python 3 strings. For + Python 2.7, replace all occurrences of ``str`` with ``unicode`` and + ``bytes`` with ``str``. Python 2.7 users may find it best to use ``from + __future__ import unicode_literals`` to avoid unintentionally using ``str`` + instead of ``unicode``. Passing Python strings to C++ ============================= -When a Python ``str`` is passed from Python to a C++ function that accepts ``std::string`` or ``char *`` as arguments, pybind11 will encode the Python string to UTF-8. All Python ``str`` can be encoded in UTF-8, so this operation does not fail. +When a Python ``str`` is passed from Python to a C++ function that accepts +``std::string`` or ``char *`` as arguments, pybind11 will encode the Python +string to UTF-8. All Python ``str`` can be encoded in UTF-8, so this operation +does not fail. -The C++ language is encoding agnostic. It is the responsibility of the programmer to track encodings. It's often easiest to simply `use UTF-8 everywhere <http://utf8everywhere.org/>`_. +The C++ language is encoding agnostic. It is the responsibility of the +programmer to track encodings. It's often easiest to simply `use UTF-8 +everywhere <http://utf8everywhere.org/>`_. .. code-block:: c++ @@ -39,20 +48,27 @@ The C++ language is encoding agnostic. It is the responsibility of the programme .. note:: - Some terminal emulators do not support UTF-8 or emoji fonts and may not display the example above correctly. + Some terminal emulators do not support UTF-8 or emoji fonts and may not + display the example above correctly. -The results are the same whether the C++ function accepts arguments by value or reference, and whether or not ``const`` is used. +The results are the same whether the C++ function accepts arguments by value or +reference, and whether or not ``const`` is used. Passing bytes to C++ -------------------- -A Python ``bytes`` object will be passed to C++ functions that accept ``std::string`` or ``char*`` *without* conversion. +A Python ``bytes`` object will be passed to C++ functions that accept +``std::string`` or ``char*`` *without* conversion. Returning C++ strings to Python =============================== -When a C++ function returns a ``std::string`` or ``char*`` to a Python caller, **pybind11 will assume that the string is valid UTF-8** and will decode it to a native Python ``str``, using the same API as Python uses to perform ``bytes.decode('utf-8')``. If this implicit conversion fails, pybind11 will raise a ``UnicodeDecodeError``. +When a C++ function returns a ``std::string`` or ``char*`` to a Python caller, +**pybind11 will assume that the string is valid UTF-8** and will decode it to a +native Python ``str``, using the same API as Python uses to perform +``bytes.decode('utf-8')``. If this implicit conversion fails, pybind11 will +raise a ``UnicodeDecodeError``. .. code-block:: c++ @@ -68,16 +84,22 @@ When a C++ function returns a ``std::string`` or ``char*`` to a Python caller, * True -Because UTF-8 is inclusive of pure ASCII, there is never any issue with returning a pure ASCII string to Python. If there is any possibility that the string is not pure ASCII, it is necessary to ensure the encoding is valid UTF-8. +Because UTF-8 is inclusive of pure ASCII, there is never any issue with +returning a pure ASCII string to Python. If there is any possibility that the +string is not pure ASCII, it is necessary to ensure the encoding is valid +UTF-8. .. warning:: - Implicit conversion assumes that a returned ``char *`` is null-terminated. If there is no null terminator a buffer overrun will occur. + Implicit conversion assumes that a returned ``char *`` is null-terminated. + If there is no null terminator a buffer overrun will occur. Explicit conversions -------------------- -If some C++ code constructs a ``std::string`` that is not a UTF-8 string, one can perform a explicit conversion and return a ``py::str`` object. Explicit conversion has the same overhead as implicit conversion. +If some C++ code constructs a ``std::string`` that is not a UTF-8 string, one +can perform a explicit conversion and return a ``py::str`` object. Explicit +conversion has the same overhead as implicit conversion. .. code-block:: c++ @@ -95,15 +117,20 @@ If some C++ code constructs a ``std::string`` that is not a UTF-8 string, one ca >>> str_output() 'Send your résumé to Alice in HR' -The `Python C API <https://docs.python.org/3/c-api/unicode.html#built-in-codecs>`_ provides several built-in codecs. +The `Python C API +<https://docs.python.org/3/c-api/unicode.html#built-in-codecs>`_ provides +several built-in codecs. -One could also use a third party encoding library such as libiconv to transcode to UTF-8. +One could also use a third party encoding library such as libiconv to transcode +to UTF-8. Return C++ strings without conversion ------------------------------------- -If the data in a C++ ``std::string`` does not represent text and should be returned to Python as ``bytes``, then one can return the data as a ``py::bytes`` object. +If the data in a C++ ``std::string`` does not represent text and should be +returned to Python as ``bytes``, then one can return the data as a +``py::bytes`` object. .. code-block:: c++ @@ -120,7 +147,8 @@ If the data in a C++ ``std::string`` does not represent text and should be retur b'\xba\xd0\xba\xd0' -Note the asymmetry: pybind11 will convert ``bytes`` to ``std::string`` without encoding, but cannot convert ``std::string`` back to ``bytes`` implicitly. +Note the asymmetry: pybind11 will convert ``bytes`` to ``std::string`` without +encoding, but cannot convert ``std::string`` back to ``bytes`` implicitly. .. code-block:: c++ @@ -128,7 +156,7 @@ Note the asymmetry: pybind11 will convert ``bytes`` to ``std::string`` without e [](std::string s) { // Accepts str or bytes from Python return s; // Looks harmless, but implicitly converts to str } - ); + ); .. code-block:: python @@ -142,7 +170,12 @@ Note the asymmetry: pybind11 will convert ``bytes`` to ``std::string`` without e Wide character strings ====================== -When a Python ``str`` is passed to a C++ function expecting ``std::wstring``, ``wchar_t*``, ``std::u16string`` or ``std::u32string``, the ``str`` will be encoded to UTF-16 or UTF-32 depending on how the C++ compiler implements each type, in the platform's endian. When strings of these types are returned, they are assumed to contain valid UTF-16 or UTF-32, and will be decoded to Python ``str``. +When a Python ``str`` is passed to a C++ function expecting ``std::wstring``, +``wchar_t*``, ``std::u16string`` or ``std::u32string``, the ``str`` will be +encoded to UTF-16 or UTF-32 depending on how the C++ compiler implements each +type, in the platform's native endianness. When strings of these types are +returned, they are assumed to contain valid UTF-16 or UTF-32, and will be +decoded to Python ``str``. .. code-block:: c++ @@ -171,17 +204,23 @@ When a Python ``str`` is passed to a C++ function expecting ``std::wstring``, `` .. warning:: - Wide character strings may not work as described on Python 2.7 or Python 3.3 compiled with ``--enable-unicode=ucs2``. + Wide character strings may not work as described on Python 2.7 or Python + 3.3 compiled with ``--enable-unicode=ucs2``. -Strings in multibyte encodings such as Shift-JIS must transcoded to a UTF-8/16/32 before being returned to Python. +Strings in multibyte encodings such as Shift-JIS must transcoded to a +UTF-8/16/32 before being returned to Python. Character literals ================== -C++ functions that accept character literals as input will receive the first character of a Python ``str`` as their input. If the string is longer than one Unicode character, trailing characters will be ignored. +C++ functions that accept character literals as input will receive the first +character of a Python ``str`` as their input. If the string is longer than one +Unicode character, trailing characters will be ignored. -When a character literal is returned from C++ (such as a ``char`` or a ``wchar_t``), it will be converted to a ``str`` that represents the single character. +When a character literal is returned from C++ (such as a ``char`` or a +``wchar_t``), it will be converted to a ``str`` that represents the single +character. .. code-block:: c++ @@ -189,26 +228,34 @@ When a character literal is returned from C++ (such as a ``char`` or a ``wchar_t m.def("pass_wchar", [](wchar_t w) { return w; }); .. code-block:: python - + >>> example.pass_char('A') 'A' -While C++ will cast integers to character types (``char c = 0x65;``), pybind11 does not convert Python integers to characters implicitly. The Python function ``chr()`` can be used to convert integers to characters. +While C++ will cast integers to character types (``char c = 0x65;``), pybind11 +does not convert Python integers to characters implicitly. The Python function +``chr()`` can be used to convert integers to characters. .. code-block:: python - + >>> example.pass_char(0x65) TypeError >>> example.pass_char(chr(0x65)) 'A' -If the desire is to work with an 8-bit integer, use ``int8_t`` or ``uint8_t`` as the argument type. +If the desire is to work with an 8-bit integer, use ``int8_t`` or ``uint8_t`` +as the argument type. Grapheme clusters ----------------- -A single grapheme may be represented by two or more Unicode characters. For example 'é' is usually represented as U+00E9 but can also be expressed as the combining character sequence U+0065 U+0301 (that is, the letter 'e' followed by a combining acute accent). The combining character will be lost if the two-character sequence is passed as an argument, even though it renders as a single grapheme. +A single grapheme may be represented by two or more Unicode characters. For +example 'é' is usually represented as U+00E9 but can also be expressed as the +combining character sequence U+0065 U+0301 (that is, the letter 'e' followed by +a combining acute accent). The combining character will be lost if the +two-character sequence is passed as an argument, even though it renders as a +single grapheme. .. code-block:: python @@ -226,18 +273,31 @@ A single grapheme may be represented by two or more Unicode characters. For exam >>> example.pass_wchar(combining_e_acute) 'e' -Normalizing combining characters before passing the character literal to C++ may resolve *some* of these issues: +Normalizing combining characters before passing the character literal to C++ +may resolve *some* of these issues: .. code-block:: python >>> example.pass_wchar(unicodedata.normalize('NFC', combining_e_acute)) 'é' -In some languages (Thai for example), there are `graphemes that cannot be expressed as a single Unicode code point <http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries>`_, so there is no way to capture them in a C++ character type. +In some languages (Thai for example), there are `graphemes that cannot be +expressed as a single Unicode code point +<http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries>`_, so there is +no way to capture them in a C++ character type. + + +C++17 string views +================== +C++17 string views are automatically supported when compiling in C++17 mode. +They follow the same rules for encoding and decoding as the corresponding STL +string type (for example, a ``std::u16string_view`` argument will be passed +UTF-16-encoded data, and a returned ``std::string_view`` will be decoded as +UTF-8). References ========== * `The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) <https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/>`_ -* `C++ - Using STL Strings at Win32 API Boundaries <https://msdn.microsoft.com/en-ca/magazine/mt238407.aspx>`_
\ No newline at end of file +* `C++ - Using STL Strings at Win32 API Boundaries <https://msdn.microsoft.com/en-ca/magazine/mt238407.aspx>`_ |