aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/doc/typesystem_manipulating_objects.rst
blob: 453fa675284729b41415b06e95d77481174df55b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
.. _manipulating-object-and-value-types:

Manipulating Object and Value Types
-----------------------------------

.. _inject-code:

inject-code
^^^^^^^^^^^
    The inject-code node inserts the given code into the generated code for the
    given type or function, and it is a child of the :ref:`object-type`, :ref:`value-type`,
    :ref:`modify-function` and :ref:`add-function` nodes.

    The code can be embedded into XML (be careful to use the correct XML entities
    for characters like '<', '>', '&'):

    .. code-block:: xml

         <value-type>
             <inject-code class="native | target | target-declaration"
                 position="beginning | end" since="...">
                 // the code
             </inject-code>
         </value-type>

    or obtained from an external file:

    .. code-block:: xml

         <value-type>
             <inject-code class="native | target | target-declaration"
                 position="beginning | end" since="..."
                 file="external_source.cpp"
                 snippet="label"/>
         </value-type>


    The ``class`` attribute specifies which module of the generated code that
    will be affected by the code injection
    (see :ref:`codegenerationterminology`). The ``class`` attribute accepts the
    following values:

        * native: The c++ code
        * target: The binding code
        * target-declaration: The code will be injected into the generated header
          file containing the c++ wrapper class definition.
        * file: The file name
        * snippet: The snippet label (optional)

    If the ``position`` attribute is set to *beginning* (the default), the code
    is inserted at the beginning of the function. If it is set to *end*, the code
    is inserted at the end of the function.

    The ``since`` attribute specify the API version where this code was injected.

    If a ``snippet`` label is given, the code between annotations of the form

    .. code-block:: c++

        // @snippet label
        ...
        // @snippet label

    will be extracted.

    For a detailed description, see :ref:`codeinjectionsemantics`.

modify-field
^^^^^^^^^^^^

    The modify-field node allows you to alter the access privileges for a given
    C++ field when mapping it onto the target language, and it is a child of an
    :ref:`object-type` or a :ref:`value-type` node.

    .. code-block:: xml

         <object-type>
             <modify-field name="..."
                 write="true | false"
                 read="true | false" />
         </object-type>

    The ``name`` attribute is the name of the field, the *optional* ``write``
    and ``read`` attributes specify the field's access privileges in the target
    language API (both are set to true by default).
    The ``remove`` attribute is an *optional* attribute, which can mark the field
    to be discarded on generation; it has the same purpose of the deprecated tag
    :ref:`remove`.

.. _modify-function:

modify-function
^^^^^^^^^^^^^^^

    The modify-function node allows you to modify a given C++ function when mapping
    it onto the target language, and it is a child of an :ref:`object-type` or a :ref:`value-type`
    node. Use the :ref:`modify-argument` node to specify which argument the modification
    affects.

    .. code-block:: xml

         <object-type>
             <modify-function signature="..."
                              since="..."
                              remove="all | c++"
                              access="public | private | protected"
                              allow-thread="true | auto | false"
                              exception-handling="off | auto-off | auto-on | on"
                              overload-number="number"
                              rename="..." />
         </object-type>

    The ``signature`` attribute is a normalized C++ signature, excluding return
    values but including potential const declarations.

    The ``since`` attribute specify the API version when this function was modified.

    The ``allow-thread`` attribute specifies whether a function should be wrapped
    into ``Py_BEGIN_ALLOW_THREADS`` and ``Py_END_ALLOW_THREADS``, that is,
    temporarily release the GIL (global interpreter lock). Doing so is required
    for any thread-related  function (wait operations), functions that might call
    a virtual function (potentially reimplemented in Python), and recommended for
    lengthy I/O operations or similar. It has performance costs, though.
    The value ``auto`` means that it will be turned off for functions for which
    it is deemed to be safe, for example, simple getters.
    The attribute defaults to ``false``.

    The ``exception-handling`` attribute specifies whether to generate exception
    handling code (nest the function call into try / catch statements). It accepts
    the following values:

           * no, false: Do not generate exception handling code
           * auto-off: Generate exception handling code for functions
             declaring a non-empty ``throw`` list
           * auto-on: Generate exception handling code unless function
             declares ``noexcept``
           * yes, true: Always generate exception handling code

    The optional ``overload-number`` attribute specifies the position of the
    overload when checking arguments. Typically, when a number of overloads
    exists, as for in example in Qt:

    .. code-block:: c++

        void QPainter::drawLine(QPointF, QPointF);
        void QPainter::drawLine(QPoint, QPoint);

    they will be reordered such that the check for matching arguments for the
    one taking a ``QPoint`` is done first. This is to avoid a potentially
    costly implicit conversion from ``QPoint`` to ``QPointF`` when using the
    2nd overload. There are cases though in which this is not desired;
    most prominently when a class inherits from a container and overloads exist
    for both types as is the case for the ``QPolygon`` class:

    .. code-block:: c++

        class QPolygon : public QList<QPoint> {};

        void QPainter::drawPolygon(QPolygon);
        void QPainter::drawPolygon(QList<QPoint>);

    By default, the overload taking a ``QList`` will be checked first, trying
    to avoid constructing a ``QPolygon`` from ``QList``. The type check for a
    list of points will succeed for a parameter of type ``QPolygon``, too,
    since it inherits ``QList``. This presents a problem since the sequence
    type check is costly due to it checking that each container element is a
    ``QPoint``. It is thus preferable to check for the ``QPolygon`` overload
    first. This is achieved by specifying numbers as follows:

    .. code-block:: xml

        <object-type name="QPainter">
            <modify-function signature="drawPolygon(QPolygon)" overload-number="0"/>
            <modify-function signature="drawPolygon(QList&lt;QPoint&gt;)" overload-number="1"/>
        </object-type>

    Numbers should be given for all overloads; otherwise, the order will be in
    declaration order.

    The ``remove``, ``access`` and ``rename`` attributes are *optional* attributes
    for added convenience; they serve the same purpose as the deprecated tags :ref:`remove`, :ref:`access` and :ref:`rename`.

.. _add-function:

add-function
^^^^^^^^^^^^

    The add-function node allows you to add a given function onto the target language,
    and it is a child of an :ref:`object-type` or :ref:`value-type` nodes if the
    function is supposed to be a method, or :ref:`namespace` and :ref:`typesystem` if
    the function is supposed to be a function inside a namespace or a global function.

    Typically when adding a function some code must be injected to provide the function
    logic. This can be done using the :ref:`inject-code` node.

    .. code-block:: xml

         <object-type>
             <add-function signature="..." return-type="..." access="public | protected" static="yes | no" since="..."/>
         </object-type>

    The ``return-type`` attribute defaults to *void*, the ``access`` to *public* and the ``static`` one to *no*.

    The ``since`` attribute specify the API version when this function was added.

    Within the signature, names for the function parameters can be specified by
    enclosing them within the delimiter *@*:

    .. code-block::

        void foo(int @parameter1@,float)

.. _declare-function:

declare-function
^^^^^^^^^^^^^^^^

    The declare-function node allows you to declare a function present in the
    type.

    .. code-block:: xml

         <container-type>
             <declare-function signature="..." return-type="..." since="..."/>
         </container-type>

    The ``return-type`` attribute defaults to *void*.

    The ``since`` attribute specifies the API version when this function was
    added.

    This is useful to make functions known to shiboken which its code parser
    does not detect. For example, in Qt 6, the ``append()`` function of the
    ``QList<T>`` container takes an argument of ``parameter_type`` which is
    specialized to ``T`` for simple types and ``const T &`` for complex types
    by some template expression which the code parser cannot resolve.
    In that case, the function can be declared with a simple signature:

    .. code-block:: xml

         <container-type name="QList">
             <declare-function signature="append(T)"/>
         </container-type>

    This tells shiboken a public function of that signature exists and
    bindings will be created in specializations of ``QList``.

.. _conversion-rule-on-types:

conversion-rule
^^^^^^^^^^^^^^^

    The conversion-rule node allows you to write customized code to convert the given argument between the target
    language and C++, and is a child of the :ref:`value-type`, :ref:`object-type`, :ref:`primitive-type` and
    :ref:`container-type` nodes.

    The code pointed by the file attribute is very tied to the generator using APIExtractor, so it don't follow any
    rules, but the generator rules..

    .. code-block:: xml

        <value-type name="Foo">
            <convertion-rule file="my_converter_implementation.h" since="..."/>
        </value-type>

    The ``since`` attribute specify the API version when this conversion rule became valid.

    .. note:: You can also use the conversion-rule node to specify :ref:`how the conversion of a single function argument should be done in a function <conversion-rule>`.

    The ``file`` and ``snippet`` attributes are also supported (see :ref:`inject-code` nodes).


property
^^^^^^^^

    The ``property`` element allows you to specify properties consisting of
    a type and getter and setter functions.

    It may appear as a child of a complex type such as ``object-type`` or
    ``value-type``.

    If the PySide6 extension is not present, code will be generated using the
    ``PyGetSetDef`` struct, similar to what is generated for fields.

    If the PySide6 extension is present, those properties complement the
    properties obtained from the ``Q_PROPERTY`` macro in Qt-based code.
    The properties will be handled in ``libpyside`` unless code generation
    is forced.

    .. code-block:: xml

        <property name="..." type="..." get="..." set="..." " generate-getsetdef="yes | no" since="..."/>

    The ``name`` attribute specifies the name of the property, the ``type``
    attribute specifies the C++ type and the ``get`` attribute specifies the
    name of the accessor function.

    The optional ``set`` attribute specifies name of the setter function.

    The optional ``generate-getsetdef`` attribute specifies whether to generate
    code for if the PySide6 extension is present (indicating this property is not
    handled by libpyside). It defaults to *no*.

    The optional ``since`` attribute specifies the API version when this
    property appears.

    For a typical C++ class, like:

    .. code-block:: c++

        class Test {
        public:
            int getValue() const;
            void setValue();
        };

    ``value`` can then be specified to be a property:

    .. code-block:: xml

        <value-type name="Test">
            <property name="value" type="int" get="getValue" set="setValue"/>

    With that, a more pythonic style can be used:

    .. code-block:: python

        test = Test()
        test.value = 42

    For Qt classes (with the PySide6 extension present), additional setters
    and getters that do not appear as ``Q_PROPERTY``, can be specified to
    be properties:

    .. code-block:: xml

        <object-type name="QMainWindow">
            <property name="centralWidget" type="QWidget *" get="centralWidget" set="setCentralWidget"/>

    in addition to the normal properties of ``QMainWindow`` defined for
    Qt Designer usage.

    .. note:: In the *Qt* coding style, the property name typically conflicts
        with the getter name. It is recommended to exclude the getter from the
        wrapper generation using the ``remove`` function modification.