You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
500 lines
18 KiB
500 lines
18 KiB
13 years ago
|
SIP Specification Files
|
||
|
=======================
|
||
|
|
||
|
A SIP specification consists of some C/C++ type and function declarations and
|
||
|
some directives. The declarations may contain annotations which provide SIP
|
||
|
with additional information that cannot be expressed in C/C++. SIP does not
|
||
|
include a full C/C++ parser.
|
||
|
|
||
|
It is important to understand that a SIP specification describes the Python
|
||
|
API, i.e. the API available to the Python programmer when they ``import`` the
|
||
|
generated module. It does not have to accurately represent the underlying
|
||
|
C/C++ library. There is nothing wrong with omitting functions that make
|
||
|
little sense in a Python context, or adding functions implemented with
|
||
|
handwritten code that have no C/C++ equivalent. It is even possible (and
|
||
|
sometimes necessary) to specify a different super-class hierarchy for a C++
|
||
|
class. All that matters is that the generated code compiles properly.
|
||
|
|
||
|
In most cases the Python API matches the C/C++ API. In some cases handwritten
|
||
|
code (see :directive:`%MethodCode`) is used to map from one to the other
|
||
|
without SIP having to know the details itself. However, there are a few cases
|
||
|
where SIP generates a thin wrapper around a C++ method or constructor (see
|
||
|
:ref:`ref-derived-classes`) and needs to know the exact C++ signature. To deal
|
||
|
with these cases SIP allows two signatures to be specified. For example::
|
||
|
|
||
|
class Klass
|
||
|
{
|
||
|
public:
|
||
|
// The Python signature is a tuple, but the underlying C++ signature
|
||
|
// is a 2 element array.
|
||
|
Klass(SIP_PYTUPLE) [(int *)];
|
||
|
%MethodCode
|
||
|
int iarr[2];
|
||
|
|
||
|
if (PyArg_ParseTuple(a0, "ii", &iarr[0], &iarr[1]))
|
||
|
{
|
||
|
// Note that we use the SIP generated derived class
|
||
|
// constructor.
|
||
|
Py_BEGIN_ALLOW_THREADS
|
||
|
sipCpp = new sipKlass(iarr);
|
||
|
Py_END_ALLOW_THREADS
|
||
|
}
|
||
|
%End
|
||
|
};
|
||
|
|
||
|
|
||
|
Syntax Definition
|
||
|
-----------------
|
||
|
|
||
|
The following is a semi-formal description of the syntax of a specification
|
||
|
file.
|
||
|
|
||
|
.. parsed-literal::
|
||
|
|
||
|
*specification* ::= {*module-statement*}
|
||
|
|
||
|
*module-statement* ::= [*module-directive* | *statement*]
|
||
|
|
||
|
*module-directive* ::= [
|
||
|
:directive:`%API` |
|
||
|
:directive:`%CModule` |
|
||
|
:directive:`%CompositeModule` |
|
||
|
:directive:`%ConsolidatedModule` |
|
||
|
:directive:`%Copying` |
|
||
|
:directive:`%DefaultEncoding` |
|
||
|
:directive:`%DefaultMetatype` |
|
||
|
:directive:`%DefaultSupertype` |
|
||
|
:directive:`%Doc` |
|
||
|
:directive:`%ExportedDoc` |
|
||
|
:directive:`%ExportedHeaderCode` |
|
||
|
:directive:`%Feature` |
|
||
|
:directive:`%Import` |
|
||
|
:directive:`%Include` |
|
||
|
:directive:`%InitialisationCode` |
|
||
|
:directive:`%License` |
|
||
|
:directive:`%MappedType` |
|
||
|
:directive:`%Module` |
|
||
|
:directive:`%ModuleCode` |
|
||
|
:directive:`%ModuleHeaderCode` |
|
||
|
:directive:`%OptionalInclude` |
|
||
|
:directive:`%Platforms` |
|
||
|
:directive:`%PreInitialisationCode` |
|
||
|
:directive:`%PostInitialisationCode` |
|
||
|
:directive:`%Timeline` |
|
||
|
:directive:`%UnitCode` |
|
||
|
*mapped-type-template*]
|
||
|
|
||
|
*statement* :: [*class-statement* | *function* | *variable*]
|
||
|
|
||
|
*class-statement* :: [
|
||
|
:directive:`%If` |
|
||
|
*class* |
|
||
|
*class-template* |
|
||
|
*enum* |
|
||
|
*namespace* |
|
||
|
*opaque-class* |
|
||
|
*operator* |
|
||
|
*struct* |
|
||
|
*typedef* |
|
||
|
*exception*]
|
||
|
|
||
|
*class* ::= **class** *name* [**:** *super-classes*] [*class-annotations*]
|
||
|
**{** {*class-line*} **};**
|
||
|
|
||
|
*super-classes* ::= *name* [**,** *super-classes*]
|
||
|
|
||
|
*class-line* ::= [
|
||
|
*class-statement* |
|
||
|
:directive:`%BIGetBufferCode` |
|
||
|
:directive:`%BIGetReadBufferCode` |
|
||
|
:directive:`%BIGetWriteBufferCode` |
|
||
|
:directive:`%BIGetSegCountCode` |
|
||
|
:directive:`%BIGetCharBufferCode` |
|
||
|
:directive:`%BIReleaseBufferCode` |
|
||
|
:directive:`%ConvertToSubClassCode` |
|
||
|
:directive:`%ConvertToTypeCode` |
|
||
|
:directive:`%Docstring` |
|
||
|
:directive:`%GCClearCode` |
|
||
|
:directive:`%GCTraverseCode` |
|
||
|
:directive:`%PickleCode` |
|
||
|
:directive:`%TypeCode` |
|
||
|
:directive:`%TypeHeaderCode` |
|
||
|
*constructor* |
|
||
|
*destructor* |
|
||
|
*method* |
|
||
|
*static-method* |
|
||
|
*virtual-method* |
|
||
|
*special-method* |
|
||
|
*operator* |
|
||
|
*virtual-operator* |
|
||
|
*class-variable* |
|
||
|
**public:** |
|
||
|
**public Q_SLOTS:** |
|
||
|
**public slots:** |
|
||
|
**protected:** |
|
||
|
**protected Q_SLOTS:** |
|
||
|
**protected slots:** |
|
||
|
**private:** |
|
||
|
**private Q_SLOTS:** |
|
||
|
**private slots:** |
|
||
|
**Q_SIGNALS:** |
|
||
|
**signals:**]
|
||
|
|
||
|
*constructor* ::= [**explicit**] *name* **(** [*argument-list*] **)**
|
||
|
[*exceptions*] [*function-annotations*]
|
||
|
[*c++-constructor-signature*] **;** [:directive:`%Docstring`]
|
||
|
[:directive:`%MethodCode`]
|
||
|
|
||
|
*c++-constructor-signature* ::= **[(** [*argument-list*] **)]**
|
||
|
|
||
|
*destructor* ::= [**virtual**] **~** *name* **()** [*exceptions*] [**= 0**]
|
||
|
[*function-annotations*] **;** [:directive:`%MethodCode`]
|
||
|
[:directive:`%VirtualCatcherCode`]
|
||
|
|
||
|
*method* ::= [**Q_SIGNAL**] [**Q_SLOT**] *type* *name* **(**
|
||
|
[*argument-list*] **)** [**const**] [*exceptions*] [**= 0**]
|
||
|
[*function-annotations*] [*c++-signature*] **;**
|
||
|
[:directive:`%Docstring`] [:directive:`%MethodCode`]
|
||
|
|
||
|
*c++-signature* ::= **[** *type* **(** [*argument-list*] **)]**
|
||
|
|
||
|
*static-method* ::= **static** *function*
|
||
|
|
||
|
*virtual-method* ::= [**Q_SIGNAL**] [**Q_SLOT**] **virtual** *type* *name*
|
||
|
**(** [*argument-list*] **)** [**const**] [*exceptions*] [**= 0**]
|
||
|
[*function-annotations*] [*c++-signature*] **;**
|
||
|
[:directive:`%MethodCode`] [:directive:`%VirtualCatcherCode`]
|
||
|
|
||
|
*special-method* ::= *type* *special-method-name*
|
||
|
**(** [*argument-list*] **)** [*function-annotations*] **;**
|
||
|
[:directive:`%MethodCode`]
|
||
|
|
||
|
*special-method-name* ::= [**__abs__** | **__add__** | **__and__** |
|
||
|
**__bool__** | **__call__** | **__cmp__** | **__contains__** |
|
||
|
**__delitem__** | **__div__** | **__eq__** | **__float__** |
|
||
|
**__floordiv__** | **__ge__** | **__getitem__** | **__gt__** |
|
||
|
**__hash__** | **__iadd__** | **__iand__** | **__idiv__** |
|
||
|
**__ifloordiv__** | **__ilshift__** | **__imod__** | **__imul__** |
|
||
|
**__index__** | **__int__** | **__invert__** | **__ior__** |
|
||
|
**__irshift__** | **__isub__** | **__iter__** | **__itruediv__** |
|
||
|
**__ixor__** | **__le__** | **__len__** | **__long__** |
|
||
|
**__lshift__** | **__lt__** | **__mod__** | **__mul__** |
|
||
|
**__ne__** | **__neg__** | **__next__** | **__nonzero__** |
|
||
|
**__or__** | **__pos__** | **__repr__** | **__rshift__** |
|
||
|
**__setitem__** | **__str__** | **__sub__** | **__truediv__** |
|
||
|
**__xor__**]
|
||
|
|
||
|
*operator* ::= *operator-type*
|
||
|
**(** [*argument-list*] **)** [**const**] [*exceptions*]
|
||
|
[*function-annotations*] **;** [:directive:`%MethodCode`]
|
||
|
|
||
|
*virtual-operator* ::= **virtual** *operator-type*
|
||
|
**(** [*argument-list*] **)** [**const**] [*exceptions*] [**= 0**]
|
||
|
[*function-annotations*] **;** [:directive:`%MethodCode`]
|
||
|
[:directive:`%VirtualCatcherCode`]
|
||
|
|
||
|
*operatator-type* ::= [ *operator-function* | *operator-cast* ]
|
||
|
|
||
|
*operator-function* ::= *type* **operator** *operator-name*
|
||
|
|
||
|
*operator-cast* ::= **operator** *type*
|
||
|
|
||
|
*operator-name* ::= [**+** | **-** | ***** | **/** | **%** | **&** |
|
||
|
**|** | **^** | **<<** | **>>** | **+=** | **-=** | ***=** |
|
||
|
**/=** | **%=** | **&=** | **|=** | **^=** | **<<=** | **>>=** |
|
||
|
**~** | **()** | **[]** | **<** | **<=** | **==** | **!=** |
|
||
|
**>** | **>>=** | **=**]
|
||
|
|
||
|
*class-variable* ::= [**static**] *variable*
|
||
|
|
||
|
*class-template* :: = **template** **<** *type-list* **>** *class*
|
||
|
|
||
|
*mapped-type-template* :: = **template** **<** *type-list* **>**
|
||
|
:directive:`%MappedType`
|
||
|
|
||
|
*enum* ::= **enum** [*name*] [*enum-annotations*] **{** {*enum-line*} **};**
|
||
|
|
||
|
*enum-line* ::= [:directive:`%If` | *name* [*enum-annotations*] **,**
|
||
|
|
||
|
*function* ::= *type* *name* **(** [*argument-list*] **)** [*exceptions*]
|
||
|
[*function-annotations*] **;** [:directive:`%Docstring`]
|
||
|
[:directive:`%MethodCode`]
|
||
|
|
||
|
*namespace* ::= **namespace** *name* **{** {*namespace-line*} **};**
|
||
|
|
||
|
*namespace-line* ::= [:directive:`%TypeHeaderCode` | *statement*]
|
||
|
|
||
|
*opaque-class* ::= **class** *scoped-name* **;**
|
||
|
|
||
|
*struct* ::= **struct** *name* **{** {*class-line*} **};**
|
||
|
|
||
|
*typedef* ::= **typedef** [*typed-name* | *function-pointer*]
|
||
|
*typedef-annotations* **;**
|
||
|
|
||
|
*variable*::= *typed-name* [*variable-annotations*] **;**
|
||
|
[:directive:`%AccessCode`] [:directive:`%GetCode`]
|
||
|
[:directive:`%SetCode`]
|
||
|
|
||
|
*exception* ::= :directive:`%Exception` *exception-name* [*exception-base*]
|
||
|
**{** [:directive:`%TypeHeaderCode`] :directive:`%RaiseCode` **};**
|
||
|
|
||
|
*exception-name* ::= *scoped-name*
|
||
|
|
||
|
*exception-base* ::= **(** [*exception-name* | *python-exception*] **)**
|
||
|
|
||
|
*python-exception* ::= [**SIP_Exception** | **SIP_StopIteration** |
|
||
|
**SIP_StandardError** | **SIP_ArithmeticError** |
|
||
|
**SIP_LookupError** | **SIP_AssertionError** |
|
||
|
**SIP_AttributeError** | **SIP_EOFError** |
|
||
|
**SIP_FloatingPointError** | **SIP_EnvironmentError** |
|
||
|
**SIP_IOError** | **SIP_OSError** | **SIP_ImportError** |
|
||
|
**SIP_IndexError** | **SIP_KeyError** | **SIP_KeyboardInterrupt** |
|
||
|
**SIP_MemoryError** | **SIP_NameError** | **SIP_OverflowError** |
|
||
|
**SIP_RuntimeError** | **SIP_NotImplementedError** |
|
||
|
**SIP_SyntaxError** | **SIP_IndentationError** | **SIP_TabError** |
|
||
|
**SIP_ReferenceError** | **SIP_SystemError** | **SIP_SystemExit** |
|
||
|
**SIP_TypeError** | **SIP_UnboundLocalError** |
|
||
|
**SIP_UnicodeError** | **SIP_UnicodeEncodeError** |
|
||
|
**SIP_UnicodeDecodeError** | **SIP_UnicodeTranslateError** |
|
||
|
**SIP_ValueError** | **SIP_ZeroDivisionError** |
|
||
|
**SIP_WindowsError** | **SIP_VMSError**]
|
||
|
|
||
|
*exceptions* ::= **throw (** [*exception-list*] **)**
|
||
|
|
||
|
*exception-list* ::= *scoped-name* [**,** *exception-list*]
|
||
|
|
||
|
*argument-list* ::= *argument* [**,** *argument-list*] [**,** **...**]
|
||
|
|
||
|
*argument* ::= [
|
||
|
*type* [*name*] [*argument-annotations*] [*default-value*] |
|
||
|
:stype:`SIP_ANYSLOT` [*default-value*] |
|
||
|
:stype:`SIP_QOBJECT` |
|
||
|
:stype:`SIP_RXOBJ_CON` |
|
||
|
:stype:`SIP_RXOBJ_DIS` |
|
||
|
:stype:`SIP_SIGNAL` [*default-value*] |
|
||
|
:stype:`SIP_SLOT` [*default-value*] |
|
||
|
:stype:`SIP_SLOT_CON` |
|
||
|
:stype:`SIP_SLOT_DIS`]
|
||
|
|
||
|
*default-value* ::= **=** *expression*
|
||
|
|
||
|
*expression* ::= [*value* | *value* *binary-operator* *expression*]
|
||
|
|
||
|
*value* ::= [*unary-operator*] *simple-value*
|
||
|
|
||
|
*simple-value* ::= [*scoped-name* | *function-call* | *real-value* |
|
||
|
*integer-value* | *boolean-value* | *string-value* |
|
||
|
*character-value*]
|
||
|
|
||
|
*typed-name*::= *type* *name*
|
||
|
|
||
|
*function-pointer*::= *type* **(*** *name* **)(** [*type-list*] **)**
|
||
|
|
||
|
*type-list* ::= *type* [**,** *type-list*]
|
||
|
|
||
|
*function-call* ::= *scoped-name* **(** [*value-list*] **)**
|
||
|
|
||
|
*value-list* ::= *value* [**,** *value-list*]
|
||
|
|
||
|
*real-value* ::= a floating point number
|
||
|
|
||
|
*integer-value* ::= a number
|
||
|
|
||
|
*boolean-value* ::= [**true** | **false**]
|
||
|
|
||
|
*string-value* ::= **"** {*character*} **"**
|
||
|
|
||
|
*character-value* ::= **'** *character* **'**
|
||
|
|
||
|
*unary-operator* ::= [**!** | **~** | **-** | **+**]
|
||
|
|
||
|
*binary-operator* ::= [**-** | **+** | ***** | **/** | **&** | **|**]
|
||
|
|
||
|
*argument-annotations* ::= see :ref:`ref-arg-annos`
|
||
|
|
||
|
*class-annotations* ::= see :ref:`ref-class-annos`
|
||
|
|
||
|
*enum-annotations* ::= see :ref:`ref-enum-annos`
|
||
|
|
||
|
*function-annotations* ::= see :ref:`ref-function-annos`
|
||
|
|
||
|
*typedef-annotations* ::= see :ref:`ref-typedef-annos`
|
||
|
|
||
|
*variable-annotations* ::= see :ref:`ref-variable-annos`
|
||
|
|
||
|
*type* ::= [**const**] *base-type* {*****} [**&**]
|
||
|
|
||
|
*type-list* ::= *type* [**,** *type-list*]
|
||
|
|
||
|
*base-type* ::= [*scoped-name* | *template* | **struct** *scoped-name* |
|
||
|
**char** | **signed char** | **unsigned char** | **wchar_t** |
|
||
|
**int** | **unsigned** | **unsigned int** |
|
||
|
**short** | **unsigned short** |
|
||
|
**long** | **unsigned long** |
|
||
|
**long long** | **unsigned long long** |
|
||
|
**float** | **double** |
|
||
|
**bool** |
|
||
|
**void** |
|
||
|
:stype:`SIP_PYCALLABLE` |
|
||
|
:stype:`SIP_PYDICT` |
|
||
|
:stype:`SIP_PYLIST` |
|
||
|
:stype:`SIP_PYOBJECT` |
|
||
|
:stype:`SIP_PYSLICE` |
|
||
|
:stype:`SIP_PYTUPLE` |
|
||
|
:stype:`SIP_PYTYPE`]
|
||
|
|
||
|
*scoped-name* ::= *name* [**::** *scoped-name*]
|
||
|
|
||
|
*template* ::= *scoped-name* **<** *type-list* **>**
|
||
|
|
||
|
*dotted-name* ::= *name* [**.** *dotted-name*]
|
||
|
|
||
|
*name* ::= _A-Za-z {_A-Za-z0-9}
|
||
|
|
||
|
Here is a short list of differences between C++ and the subset supported by
|
||
|
SIP that might trip you up.
|
||
|
|
||
|
- SIP does not support the use of ``[]`` in types. Use pointers instead.
|
||
|
|
||
|
- A global ``operator`` can only be defined if its first argument is a
|
||
|
class or a named enum that has been wrapped in the same module.
|
||
|
|
||
|
- Variables declared outside of a class are effectively read-only.
|
||
|
|
||
|
- A class's list of super-classes doesn't not include any access specifier
|
||
|
(e.g. ``public``).
|
||
|
|
||
|
|
||
|
Variable Numbers of Arguments
|
||
|
-----------------------------
|
||
|
|
||
|
SIP supports the use of ``...`` as the last part of a function signature. Any
|
||
|
remaining arguments are collected as a Python tuple.
|
||
|
|
||
|
|
||
|
Additional SIP Types
|
||
|
--------------------
|
||
|
|
||
|
SIP supports a number of additional data types that can be used in Python
|
||
|
signatures.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_ANYSLOT
|
||
|
|
||
|
This is both a ``const char *`` and a ``PyObject *`` that is used as the type
|
||
|
of the member instead of ``const char *`` in functions that implement the
|
||
|
connection or disconnection of an explicitly generated signal to a slot.
|
||
|
Handwritten code must be provided to interpret the conversion correctly.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_PYCALLABLE
|
||
|
|
||
|
This is a ``PyObject *`` that is a Python callable object.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_PYDICT
|
||
|
|
||
|
This is a ``PyObject *`` that is a Python dictionary object.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_PYLIST
|
||
|
|
||
|
This is a ``PyObject *`` that is a Python list object.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_PYOBJECT
|
||
|
|
||
|
This is a ``PyObject *`` of any Python type.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_PYSLICE
|
||
|
|
||
|
This is a ``PyObject *`` that is a Python slice object.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_PYTUPLE
|
||
|
|
||
|
This is a ``PyObject *`` that is a Python tuple object.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_PYTYPE
|
||
|
|
||
|
This is a ``PyObject *`` that is a Python type object.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_QOBJECT
|
||
|
|
||
|
This is a ``QObject *`` that is a C++ instance of a class derived from Qt's
|
||
|
``QObject`` class.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_RXOBJ_CON
|
||
|
|
||
|
This is a ``QObject *`` that is a C++ instance of a class derived from Qt's
|
||
|
``QObject`` class. It is used as the type of the receiver instead of ``const
|
||
|
QObject *`` in functions that implement a connection to a slot.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_RXOBJ_DIS
|
||
|
|
||
|
This is a ``QObject *`` that is a C++ instance of a class derived from Qt's
|
||
|
``QObject`` class. It is used as the type of the receiver instead of ``const
|
||
|
QObject *`` in functions that implement a disconnection from a slot.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_SIGNAL
|
||
|
|
||
|
This is a ``const char *`` that is used as the type of the signal instead of
|
||
|
``const char *`` in functions that implement the connection or disconnection
|
||
|
of an explicitly generated signal to a slot.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_SLOT
|
||
|
|
||
|
This is a ``const char *`` that is used as the type of the member instead of
|
||
|
``const char *`` in functions that implement the connection or disconnection
|
||
|
of an explicitly generated signal to a slot.
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_SLOT_CON
|
||
|
|
||
|
This is a ``const char *`` that is used as the type of the member instead of
|
||
|
``const char *`` in functions that implement the connection of an internally
|
||
|
generated signal to a slot. The type includes a comma separated list of types
|
||
|
that is the C++ signature of of the signal.
|
||
|
|
||
|
To take an example, ``QAccel::connectItem()`` connects an internally generated
|
||
|
signal to a slot. The signal is emitted when the keyboard accelerator is
|
||
|
activated and it has a single integer argument that is the ID of the
|
||
|
accelerator. The C++ signature is::
|
||
|
|
||
|
bool connectItem(int id, const QObject *receiver, const char *member);
|
||
|
|
||
|
The corresponding SIP specification is::
|
||
|
|
||
|
bool connectItem(int, SIP_RXOBJ_CON, SIP_SLOT_CON(int));
|
||
|
|
||
|
|
||
|
.. sip-type:: SIP_SLOT_DIS
|
||
|
|
||
|
This is a ``const char *`` that is used as the type of the member instead of
|
||
|
``const char *`` in functions that implement the disconnection of an
|
||
|
internally generated signal to a slot. The type includes a comma separated
|
||
|
list of types that is the C++ signature of of the signal.
|
||
|
|
||
|
|
||
|
Classic Division and True Division
|
||
|
----------------------------------
|
||
|
|
||
|
SIP supports the ``__div__`` and ``__truediv__`` special methods (and the
|
||
|
corresponding inplace versions) for both Python v2 and v3.
|
||
|
|
||
|
For Python v2 the ``__div__`` method will be used for both classic and true
|
||
|
division if a ``__truediv__`` method is not defined.
|
||
|
|
||
|
For Python v3 the ``__div__`` method will be used for true division if a
|
||
|
``__truediv__`` method is not defined.
|
||
|
|
||
|
For all versions of Python, if both methods are defined then ``__div__``
|
||
|
should be defined first.
|