aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/doc/typesystem_manipulating_objects.rst
blob: e024cdf0002fae3d6446b522f41673898cca159f (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
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
.. _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.
It may contain :ref:`insert-template` child nodes.

.. code-block:: xml

    <inject-code class="native | target"
                 position="beginning | end" since="..."
                 file="[file]"
                 snippet="[label]"/>


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

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.

For a detailed description of how to above attributes interact,
see :ref:`codeinjectionsemantics`.

The optional ``file`` attribute specifies the file name
(see :ref:`external-snippets`).

The optional ``snippet`` attribute specifies the snippet label
(see :ref:`external-snippets`).

There are a number of placeholders which are replaced when injecting
code (see :ref:`typesystemvariables`).

There are severals ways to specify the code:

Embedding Code into XML
=======================

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"
             position="beginning | end" since="...">
             // the code
         </inject-code>
     </value-type>


Using a Template Specified in XML
=================================

It is possible to create code templates for reuse in XML
(see :ref:`using-code-templates`). This allows for replacing of custom
placeholders.

.. code-block:: xml

     <value-type>
         <inject-code class="native | target" class="native | target">
             <insert-template name="template_name"/>
         </inject-code>
     </value-type>


.. _external-snippets:

Using Snippets From External Files
==================================

Code or documentation snippets can also be retrieved from external
files found in the typesystem search path (see :ref:`typesystem-paths`).

.. code-block:: xml

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


In the external file ``external_source.cpp``, the code between annotations
of the form:

.. code-block:: c++

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


will be extracted.

.. _modify-field:

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"
             remove="true | false"
             opaque-container = "yes | no"
             snake-case="yes | no | both" />
     </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* boolean attribute, which can
mark the field to be discarded on generation.

The *optional* ``rename`` attribute can be used to change the name of the
given field in the generated target language API.

The *optional* ``opaque-container`` attribute specifies whether
an opaque container should be returned on read access
(see :ref:`opaque-containers`).

The *optional* **snake-case** attribute allows for overriding the value
specified on the class entry or **typesystem** element.

.. _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 a :ref:`function`,
:ref:`namespace`, :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="true | false"
                          access="public | private | protected"
                          allow-thread="true | auto | false"
                          exception-handling="no | auto-off | auto-on | yes"
                          final="true | false"
                          overload-number="number"
                          rename="..."
                          snake-case="yes | no | both"
                          deprecated = "true | false" />
     </object-type>

The ``signature`` attribute is a normalized C++ signature, excluding return
values but including potential const declarations. It is not required
when ``modify-function`` appears as a child of a :ref:`function` node to
modify a global function.

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 optional ``final`` attribute can be specified for virtual functions
and disables generating the code for overriding the function in Python
(native call). This is useful when the result type is not constructible.

The ``remove`` attribute is an *optional* boolean attribute, which can
mark the function to be discarded on generation.

The *optional* ``rename`` attribute can be used to change the name of the
given function in the generated target language API.

The *optional* ``access`` attribute changes the access privileges of the
given function in the generated target language API.

The *optional* **snake-case** attribute allows for overriding the value
specified on the class entry or **typesystem** element.

The *optional* **deprecated** attribute allows for overriding deprecation
as detected by the C++ attribute. It works in both ways.

.. _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.
It may contain :ref:`modify-argument` nodes.

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"
                       overload-number="number"
                       static="yes | no" classmethod="yes | no"
                       python-override ="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 specifies the API version when this function was added.

The ``classmethod`` attribute specifies whether the function should be a Python class method.
It sets the METH_CLASS flag which means that ``PyTypeObject`` instead of an instance
``PyObject`` is passed as self, which needs to be handled in injected code.

For the *optional* attribute ``overload-number``, see :ref:`modify-function`.

Note that the label "static" in Qt's class documentation almost always means that a Python
``classmethod`` should be generated, because an object's class is always accessible from the
static C++ code, while Python needs the explicit "self" parameter that ``classmethod``
provides.

In order to create keyword argument supporting function parameters, enclose the specific
function parameter with a *@* in the `signature` field.

.. code-block:: xml

    <add-function signature="foo(int @parameter1@,float @parameter2@)">
        ...
    </add-function>

With keyword arguments, ``add-function`` makes it easy to specify a default argument
within the `signature` field

.. code-block:: xml

    <add-function signature="foo(int @parameter1@=1,float @parameter2@=2)">
        ...
    </add-function>

See :ref:`sequence-protocol` for adding the respective functions.

The *optional* attribute ``python-override`` indicates a special type
of added function, a python-override that will be generated into
the native wrapper (see :ref:`modifying-virtual-functions`).

.. _declare-function:

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

The ``declare-function`` node allows you to declare a function present in
the type 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. It may contain :ref:`modify-argument` nodes.

.. code-block:: xml

     <container-type>
         <declare-function signature="..." return-type="..." since="..."
                           allow-thread="true | auto | false"
                           exception-handling="off | auto-off | auto-on | on"
                           overload-number="number"
                           snake-case="yes | no | both"/>
     </container-type>

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

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

For the *optional* attributes ``allow-thread``, ``exception-handling``,
``overload-number`` and ``snake-case``, see :ref:`modify-function`.

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``.


.. _add-pymethoddef:

add-pymethoddef
^^^^^^^^^^^^^^^

The ``add-pymethoddef`` element allows you to add a free function to
the ``PyMethodDef`` array of the type. No argument or result conversion
is generated, allowing for variadic functions and more flexible
arguments checking.

.. code-block:: xml

     <add-pymethoddef name="..." function="..." flags="..." doc="..."
                      signatures="..."/>

The ``name`` attribute specifies the name.

The ``function`` attribute specifies the implementation (a static function
of type ``PyCFunction``).

The ``flags`` attribute specifies the flags (typically ``METH_VARARGS``,
see `Common Object Structures`_).

The optional ``doc`` attribute specifies the documentation to be set to the
``ml_doc`` field.

The optional ``signatures`` attribute specifies a semicolon-separated list
of signatures of the function.

.. _Common Object Structures: https://docs.python.org/3/c-api/structures.html

.. _property-declare:

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 :ref:`object-type` or
:ref:`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.

.. _configuration-element:

configuration
^^^^^^^^^^^^^

The ``configuration`` element allows you to generate a preprocessor
condition excluding a type depending on an expression into the module
header. This is specifically tailored to the
`Qt Feature system <https://doc.qt.io/qt-6/configure-options.html>`_ ,
but may also be used for similar systems.

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

.. code-block:: xml

    <configuration condition="..."/>

The ``condition`` attribute specifies the preprocessor condition.

This is an alternative way of omitting classes depending on some
configuration (see also option :ref:`drop-type-entries`) intended
for building several configurations from one generated source tree,
but still requires listing the correct source files in the
``CMakeLists.txt`` file.

.. _modifying-virtual-functions:

Modifying virtual functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Some C++ virtual functions are unsuitable for Python bindings:

.. code-block:: c

    virtual void getInt(int *result) const;

In that case, you would modify it to return the integer instead (or a tuple
in case of several out-parameters):

.. code-block:: c

    virtual int getInt() const;

For the binding itself, use the common argument modifications (removing
arguments, modifying return types with injected code snippets) to modify the
signature.

To make it possible to reimplement the function in Python with the modified
signature, add a ``python-override`` function with that signature, using an
arbitrary name for disambiguation:

.. code-block:: xml

       <add-function signature="getIntPyOverride()"
                     return-type="int" python-override="true"/>

This causes a static function performing the call into Python for the override
to be generated into the native wrapper.

In the existing virtual function, inject a code snippet at the ``shell`` /
``override`` position which calls the newly added function. The first 2
arguments are the `Global interpreter lock handle` (``Shiboken::GilState``) and
the Python method determined by the override check (``PyObject *``). The
snippet then converts the arguments and return values and returns after that:

.. code-block:: xml

       <modify-function signature="getInt(int*)const">
           <inject-code class="shell" position="override">
           *result = getIntPyOverride(gil, pyOverride.object());
           return;
           </inject-code>
       </modify-function>