diff options
Diffstat (limited to 'sources/shiboken2/doc/typesystem_converters.rst')
-rw-r--r-- | sources/shiboken2/doc/typesystem_converters.rst | 291 |
1 files changed, 0 insertions, 291 deletions
diff --git a/sources/shiboken2/doc/typesystem_converters.rst b/sources/shiboken2/doc/typesystem_converters.rst deleted file mode 100644 index 872daa187..000000000 --- a/sources/shiboken2/doc/typesystem_converters.rst +++ /dev/null @@ -1,291 +0,0 @@ -**************************** -User Defined Type Conversion -**************************** - -In the process of creating Python bindings of a C++ library, most of the C++ -classes will have wrappers representing them in Python land. -But there may be other classes that are very simple and/or have a Python type -as a direct counter part. (Example: a "Complex" class, that represents complex -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++ - - // 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 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 "<conversion-rule>" tag must be used. - - .. code-block:: xml - - <primitive-type name="Complex" target-lang-api-name="PyComplex"> - <include file-name="complex.h" location="global"/> - - <conversion-rule> - - <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> - - </conversion-rule> - - </primitive-type> - - -The details will be given later, but the gist of it are the tags -:ref:`native-to-target <native-to-target>`, which has only one conversion from C++ to Python, and -:ref:`native-to-native <target-to-native>`, that may define the conversion of multiple Python types -to C++'s "Complex" type. - -.. image:: images/converter.png - :height: 240px - :align: center - -|project| expects the code for :ref:`native-to-target <native-to-target>`, to directly return the -Python result of the conversion, and the added conversions inside the -:ref:`target-to-native <target-to-native>` must attribute the Python to C++ conversion result to -the :ref:`%out <out>` variable. - -Expanding on the last example, if the binding developer want a Python 2-tuple -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 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> - - <primitive-type name="Complex" target-lang-api-name="PyComplex"> - <include file-name="complex.h" location="global"/> - - <conversion-rule> - - <native-to-target> - return PyComplex_FromDoubles(%in.real(), %in.imag()); - </native-to-target> - - <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="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> - - </conversion-rule> - - </primitive-type> - - -.. _container_conversions: - -Container Conversions -===================== - -Converters for :ref:`container-type <container-type>` are pretty much the same as for other type, -except that they make use of the type system variables -:ref:`%INTYPE_# <intype_n>` and :ref:`%OUTTYPE_# <outtype_n>`. -|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> - - </target-to-native> - </conversion-rule> - </container-type> - - -.. _variables_and_functions: - -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. - - -.. _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. - - -.. _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. - - -.. _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. |