diff options
Diffstat (limited to 'sources/shiboken6/doc/typesystem_converters.rst')
-rw-r--r-- | sources/shiboken6/doc/typesystem_converters.rst | 278 |
1 files changed, 110 insertions, 168 deletions
diff --git a/sources/shiboken6/doc/typesystem_converters.rst b/sources/shiboken6/doc/typesystem_converters.rst index 7858eb6a9..ab6fba930 100644 --- a/sources/shiboken6/doc/typesystem_converters.rst +++ b/sources/shiboken6/doc/typesystem_converters.rst @@ -12,51 +12,51 @@ numbers, has a Python equivalent in the "complex" type.) Such classes, instead of getting a Python wrapper, normally have conversions rules, from Python to C++ and vice-versa. - .. code-block:: c++ +.. code-block:: c++ - // C++ class - struct Complex { - Complex(double real, double imag); - double real() const; - double imag() const; - }; + // C++ class + struct Complex { + Complex(double real, double imag); + double real() const; + double imag() const; + }; - // Converting from C++ to Python using the CPython API: - PyObject* pyCpxObj = PyComplex_FromDoubles(complex.real(), complex.imag()); + // Converting from C++ to Python using the CPython API: + PyObject* pyCpxObj = PyComplex_FromDoubles(complex.real(), complex.imag()); - // Converting from Python to C++: - double real = PyComplex_RealAsDouble(pyCpxObj); - double imag = PyComplex_ImagAsDouble(pyCpxObj); - Complex cpx(real, imag); + // Converting from Python to C++: + double real = PyComplex_RealAsDouble(pyCpxObj); + double imag = PyComplex_ImagAsDouble(pyCpxObj); + Complex cpx(real, imag); For the user defined conversion code to be inserted in the proper places, the :ref:`conversion-rule` tag must be used. - .. code-block:: xml +.. code-block:: xml - <primitive-type name="Complex" target-lang-api-name="PyComplex"> - <include file-name="complex.h" location="global"/> + <primitive-type name="Complex" target-lang-api-name="PyComplex"> + <include file-name="complex.h" location="global"/> - <conversion-rule> + <conversion-rule> - <native-to-target> - return PyComplex_FromDoubles(%in.real(), %in.imag()); - </native-to-target> + <native-to-target> + return PyComplex_FromDoubles(%in.real(), %in.imag()); + </native-to-target> - <target-to-native> - <!-- The 'check' attribute can be derived from the 'type' attribute, - it is defined here to test the CHECKTYPE type system variable. --> - <add-conversion type="PyComplex" check="%CHECKTYPE[Complex](%in)"> - double real = PyComplex_RealAsDouble(%in); - double imag = PyComplex_ImagAsDouble(%in); - %out = %OUTTYPE(real, imag); - </add-conversion> - </target-to-native> + <target-to-native> + <!-- The 'check' attribute can be derived from the 'type' attribute, + it is defined here to test the CHECKTYPE type system variable. --> + <add-conversion type="PyComplex" check="%CHECKTYPE[Complex](%in)"> + double real = PyComplex_RealAsDouble(%in); + double imag = PyComplex_ImagAsDouble(%in); + %out = %OUTTYPE(real, imag); + </add-conversion> + </target-to-native> - </conversion-rule> + </conversion-rule> - </primitive-type> + </primitive-type> The details will be given later, but the gist of it are the tags @@ -78,53 +78,53 @@ of numbers to be accepted by wrapped C++ functions with "Complex" arguments, an :ref:`add-conversion <add-conversion>` tag and a custom check must be added. Here's how to do it: - .. code-block:: xml +.. code-block:: xml - <!-- Code injection at module level. --> - <inject-code class="native" position="beginning"> - static bool Check2TupleOfNumbers(PyObject* pyIn) { - if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2)) - return false; - Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0)); - if (!SbkNumber_Check(pyReal)) - return false; - Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1)); - if (!SbkNumber_Check(pyImag)) - return false; - return true; - } - </inject-code> + <!-- Code injection at module level. --> + <inject-code class="native" position="beginning"> + static bool Check2TupleOfNumbers(PyObject* pyIn) { + if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2)) + return false; + Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0)); + if (!PyNumber_Check(pyReal)) + return false; + Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1)); + if (!PyNumber_Check(pyImag)) + return false; + return true; + } + </inject-code> - <primitive-type name="Complex" target-lang-api-name="PyComplex"> - <include file-name="complex.h" location="global"/> + <primitive-type name="Complex" target-lang-api-name="PyComplex"> + <include file-name="complex.h" location="global"/> - <conversion-rule> + <conversion-rule> - <native-to-target> - return PyComplex_FromDoubles(%in.real(), %in.imag()); - </native-to-target> + <native-to-target> + return PyComplex_FromDoubles(%in.real(), %in.imag()); + </native-to-target> - <target-to-native> + <target-to-native> - <add-conversion type="PyComplex"> - double real = PyComplex_RealAsDouble(%in); - double imag = PyComplex_ImagAsDouble(%in); - %out = %OUTTYPE(real, imag); - </add-conversion> + <add-conversion type="PyComplex"> + double real = PyComplex_RealAsDouble(%in); + double imag = PyComplex_ImagAsDouble(%in); + %out = %OUTTYPE(real, imag); + </add-conversion> - <add-conversion type="PySequence" check="Check2TupleOfNumbers(%in)"> - Shiboken::AutoDecRef pyReal(PySequence_GetItem(%in, 0)); - Shiboken::AutoDecRef pyImag(PySequence_GetItem(%in, 1)); - double real = %CONVERTTOCPP[double](pyReal); - double imag = %CONVERTTOCPP[double](pyImag); - %out = %OUTTYPE(real, imag); - </add-conversion> + <add-conversion type="PySequence" check="Check2TupleOfNumbers(%in)"> + Shiboken::AutoDecRef pyReal(PySequence_GetItem(%in, 0)); + Shiboken::AutoDecRef pyImag(PySequence_GetItem(%in, 1)); + double real = %CONVERTTOCPP[double](pyReal); + double imag = %CONVERTTOCPP[double](pyImag); + %out = %OUTTYPE(real, imag); + </add-conversion> - </target-to-native> + </target-to-native> - </conversion-rule> + </conversion-rule> - </primitive-type> + </primitive-type> .. _container_conversions: @@ -138,43 +138,50 @@ except that they make use of the type system variables |project| combines the conversion code for containers with the conversion defined (or automatically generated) for the containers. - .. code-block:: xml - - <container-type name="std::map" type="map"> - <include file-name="map" location="global"/> - - <conversion-rule> - - <native-to-target> - PyObject* %out = PyDict_New(); - %INTYPE::const_iterator it = %in.begin(); - for (; it != %in.end(); ++it) { - %INTYPE_0 key = it->first; - %INTYPE_1 value = it->second; - PyDict_SetItem(%out, - %CONVERTTOPYTHON[%INTYPE_0](key), - %CONVERTTOPYTHON[%INTYPE_1](value)); - } - return %out; - </native-to-target> - - <target-to-native> - - <add-conversion type="PyDict"> - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - while (PyDict_Next(%in, &pos, &key, &value)) { - %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); - %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value); - %out.insert(%OUTTYPE::value_type(cppKey, cppValue)); - } - </add-conversion> +.. code-block:: xml + + <container-type name="std::map" type="map"> + <include file-name="map" location="global"/> + + <conversion-rule> + + <native-to-target> + PyObject* %out = PyDict_New(); + %INTYPE::const_iterator it = %in.begin(); + for (; it != %in.end(); ++it) { + %INTYPE_0 key = it->first; + %INTYPE_1 value = it->second; + PyDict_SetItem(%out, + %CONVERTTOPYTHON[%INTYPE_0](key), + %CONVERTTOPYTHON[%INTYPE_1](value)); + } + return %out; + </native-to-target> + + <target-to-native> + + <add-conversion type="PyDict"> + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + while (PyDict_Next(%in, &pos, &key, &value)) { + %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); + %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value); + %out.insert(%OUTTYPE::value_type(cppKey, cppValue)); + } + </add-conversion> - </target-to-native> - </conversion-rule> - </container-type> + </target-to-native> + </conversion-rule> + </container-type> +.. note:: The C++ containers ``std::list``\, ``std::vector``\, + ``std::pair``\, ``std::map``\, ``std::span`` and ``std::unordered_map`` are + built-in. + To specify :ref:`opaque-containers`, use the :ref:`opaque-container` element. + :ref:`container-type` can still be specified to modify the built-in behavior. + For this case, a number of pre-defined conversion templates + are provided (see :ref:`predefined_templates`). .. _variables_and_functions: @@ -185,14 +192,12 @@ Variables & Functions .. _in: **%in** - Variable replaced by the C++ input variable. .. _out: **%out** - Variable replaced by the C++ output variable. Needed to convey the result of a Python to C++ conversion. @@ -200,7 +205,6 @@ Variables & Functions .. _intype: **%INTYPE** - Used in Python to C++ conversions. It is replaced by the name of type for which the conversion is being defined. Don't use the type's name directly. @@ -208,14 +212,12 @@ Variables & Functions .. _intype_n: **%INTYPE_#** - Replaced by the name of the #th type used in a container. .. _outtype: **%OUTTYPE** - Used in Python to C++ conversions. It is replaced by the name of type for which the conversion is being defined. Don't use the type's name directly. @@ -223,71 +225,11 @@ Variables & Functions .. _outtype_n: **%OUTTYPE_#** - Replaced by the name of the #th type used in a container. .. _checktype: **%CHECKTYPE[CPPTYPE]** - Replaced by a |project| type checking function for a Python variable. The C++ type is indicated by ``CPPTYPE``. - - -.. _oldconverters: - -Converting The Old Converters -============================= - -If you use |project| for your bindings, and has defined some type conversions -using the ``Shiboken::Converter`` template, then you must update your converters -to the new scheme. - -Previously your conversion rules were declared in one line, like this: - - - .. code-block:: xml - - <primitive-type name="Complex" target-lang-api-name="PyComplex"> - <include file-name="complex.h" location="global"/> - <conversion-rule file="complex_conversions.h"/> - </primitive-type> - - -And implemented in a separate C++ file, like this: - - - .. code-block:: c++ - - namespace Shiboken { - template<> struct Converter<Complex> - { - static inline bool checkType(PyObject* pyObj) { - return PyComplex_Check(pyObj); - } - static inline bool isConvertible(PyObject* pyObj) { - return PyComplex_Check(pyObj); - } - static inline PyObject* toPython(void* cppobj) { - return toPython(*reinterpret_cast<Complex*>(cppobj)); - } - static inline PyObject* toPython(const Complex& cpx) { - return PyComplex_FromDoubles(cpx.real(), cpx.imag()); - } - static inline Complex toCpp(PyObject* pyobj) { - double real = PyComplex_RealAsDouble(pyobj); - double imag = PyComplex_ImagAsDouble(pyobj); - return Complex(real, imag); - } - }; - } - - -In this case, the parts of the implementation that will be used in the new -conversion-rule are the ones in the two last method -``static inline PyObject* toPython(const Complex& cpx)`` and -``static inline Complex toCpp(PyObject* pyobj)``. The ``isConvertible`` method -is gone, and the ``checkType`` is now an attribute of the :ref:`add-conversion <add-conversion>` -tag. Refer back to the first example in this page and you will be able to -correlate the above template with the new scheme of conversion rule definition. |