diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-22 02:59:34 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-22 02:59:34 -0600 |
commit | 6c4cc3653e8dd7668295f3e659b7eb4dc571b67c (patch) | |
tree | a559fd71fc982e35a4f984d85a5c9d92b764ae8c /doc/html/using.html | |
download | sip4-tqt-6c4cc3653e8dd7668295f3e659b7eb4dc571b67c.tar.gz sip4-tqt-6c4cc3653e8dd7668295f3e659b7eb4dc571b67c.zip |
Initial import of SIP4 for Qt3
Diffstat (limited to 'doc/html/using.html')
-rw-r--r-- | doc/html/using.html | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/doc/html/using.html b/doc/html/using.html new file mode 100644 index 0000000..5ff6786 --- /dev/null +++ b/doc/html/using.html @@ -0,0 +1,731 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + + <title>Using SIP — SIP 4.10.5 Reference Guide</title> + <link rel="stylesheet" href="_static/default.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + <script type="text/javascript"> + var DOCUMENTATION_OPTIONS = { + URL_ROOT: '#', + VERSION: '4.10.5', + COLLAPSE_MODINDEX: false, + FILE_SUFFIX: '.html', + HAS_SOURCE: true + }; + </script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <link rel="top" title="SIP 4.10.5 Reference Guide" href="index.html" /> + <link rel="next" title="The SIP Command Line" href="command_line.html" /> + <link rel="prev" title="Installation" href="installation.html" /> + </head> + <body> + <div class="related"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + accesskey="I">index</a></li> + <li class="right" > + <a href="modindex.html" title="Global Module Index" + accesskey="M">modules</a> |</li> + <li class="right" > + <a href="command_line.html" title="The SIP Command Line" + accesskey="N">next</a> |</li> + <li class="right" > + <a href="installation.html" title="Installation" + accesskey="P">previous</a> |</li> + <li><a href="index.html">SIP 4.10.5 Reference Guide</a> »</li> + </ul> + </div> + + <div class="document"> + <div class="documentwrapper"> + <div class="bodywrapper"> + <div class="body"> + + <div class="section" id="using-sip"> +<span id="ref-using"></span><h1>Using SIP<a class="headerlink" href="#using-sip" title="Permalink to this headline">¶</a></h1> +<p>Bindings are generated by the SIP code generator from a number of specification +files, typically with a <tt class="docutils literal"><span class="pre">.sip</span></tt> extension. Specification files look very +similar to C and C++ header files, but often with additional information (in +the form of a <em>directive</em> or an <em>annotation</em>) and code so that the bindings +generated can be finely tuned.</p> +<div class="section" id="a-simple-c-example"> +<span id="ref-simple-c-example"></span><h2>A Simple C++ Example<a class="headerlink" href="#a-simple-c-example" title="Permalink to this headline">¶</a></h2> +<p>We start with a simple example. Let’s say you have a (fictional) C++ library +that implements a single class called <tt class="docutils literal"><span class="pre">Word</span></tt>. The class has one constructor +that takes a <tt class="docutils literal"><span class="pre">\0</span></tt> terminated character string as its single argument. The +class has one method called <tt class="docutils literal"><span class="pre">reverse()</span></tt> which takes no arguments and returns +a <tt class="docutils literal"><span class="pre">\0</span></tt> terminated character string. The interface to the class is defined in +a header file called <tt class="docutils literal"><span class="pre">word.h</span></tt> which might look something like this:</p> +<div class="highlight-python"><pre>// Define the interface to the word library. + +class Word { + const char *the_word; + +public: + Word(const char *w); + + char *reverse() const; +};</pre> +</div> +<p>The corresponding SIP specification file would then look something like this:</p> +<div class="highlight-python"><pre>// Define the SIP wrapper to the word library. + +%Module word 0 + +class Word { + +%TypeHeaderCode +#include <word.h> +%End + +public: + Word(const char *w); + + char *reverse() const; +};</pre> +</div> +<p>Obviously a SIP specification file looks very much like a C++ (or C) header +file, but SIP does not include a full C++ parser. Let’s look at the +differences between the two files.</p> +<blockquote> +<ul class="simple"> +<li>The <a class="reference external" href="directives.html#directive-%Module"><tt class="xref docutils literal"><span class="pre">%Module</span></tt></a> directive has been added <a class="footnote-reference" href="#id4" id="id1">[1]</a>. This is used to +name the Python module that is being created and to give it a +<em>generation</em> number. In this example these are <tt class="docutils literal"><span class="pre">word</span></tt> and <tt class="docutils literal"><span class="pre">0</span></tt> +respectively. The generation number is effectively the version number of +the module.</li> +<li>The <a class="reference external" href="directives.html#directive-%TypeHeaderCode"><tt class="xref docutils literal"><span class="pre">%TypeHeaderCode</span></tt></a> directive has been added. The text +between this and the following <a class="reference external" href="directives.html#directive-%End"><tt class="xref docutils literal"><span class="pre">%End</span></tt></a> directive is included +literally in the code that SIP generates. Normally it is used, as in +this case, to <tt class="docutils literal"><span class="pre">#include</span></tt> the corresponding C++ (or C) header file <a class="footnote-reference" href="#id5" id="id2">[2]</a>.</li> +<li>The declaration of the private variable <tt class="docutils literal"><span class="pre">this_word</span></tt> has been removed. +SIP does not support access to either private or protected instance +variables.</li> +</ul> +</blockquote> +<p>If we want to we can now generate the C++ code in the current directory by +running the following command:</p> +<div class="highlight-python"><div class="highlight"><pre><span class="n">sip</span> <span class="o">-</span><span class="n">c</span> <span class="o">.</span> <span class="n">word</span><span class="o">.</span><span class="n">sip</span> +</pre></div> +</div> +<p>However, that still leaves us with the task of compiling the generated code and +linking it against all the necessary libraries. It’s much easier to use the +<a class="reference external" href="build_system.html#ref-build-system"><em>SIP build system</em></a> to do the whole thing.</p> +<p>Using the SIP build system is simply a matter of writing a small Python script. +In this simple example we will assume that the <tt class="docutils literal"><span class="pre">word</span></tt> library we are wrapping +and it’s header file are installed in standard system locations and will be +found by the compiler and linker without having to specify any additional +flags. In a more realistic example your Python script may take command line +options, or search a set of directories to deal with different configurations +and installations.</p> +<p>This is the simplest script (conventionally called <tt class="docutils literal"><span class="pre">configure.py</span></tt>):</p> +<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span> +<span class="kn">import</span> <span class="nn">sipconfig</span> + +<span class="c"># The name of the SIP build file generated by SIP and used by the build</span> +<span class="c"># system.</span> +<span class="n">build_file</span> <span class="o">=</span> <span class="s">"word.sbf"</span> + +<span class="c"># Get the SIP configuration information.</span> +<span class="n">config</span> <span class="o">=</span> <span class="n">sipconfig</span><span class="o">.</span><span class="n">Configuration</span><span class="p">()</span> + +<span class="c"># Run SIP to generate the code.</span> +<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s">" "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">config</span><span class="o">.</span><span class="n">sip_bin</span><span class="p">,</span> <span class="s">"-c"</span><span class="p">,</span> <span class="s">"."</span><span class="p">,</span> <span class="s">"-b"</span><span class="p">,</span> <span class="n">build_file</span><span class="p">,</span> <span class="s">"word.sip"</span><span class="p">]))</span> + +<span class="c"># Create the Makefile.</span> +<span class="n">makefile</span> <span class="o">=</span> <span class="n">sipconfig</span><span class="o">.</span><span class="n">SIPModuleMakefile</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">build_file</span><span class="p">)</span> + +<span class="c"># Add the library we are wrapping. The name doesn't include any platform</span> +<span class="c"># specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the</span> +<span class="c"># ".dll" extension on Windows).</span> +<span class="n">makefile</span><span class="o">.</span><span class="n">extra_libs</span> <span class="o">=</span> <span class="p">[</span><span class="s">"word"</span><span class="p">]</span> + +<span class="c"># Generate the Makefile itself.</span> +<span class="n">makefile</span><span class="o">.</span><span class="n">generate</span><span class="p">()</span> +</pre></div> +</div> +<p>Hopefully this script is self-documenting. The key parts are the +<tt class="docutils literal"><span class="pre">Configuration</span></tt> and <tt class="docutils literal"><span class="pre">SIPModuleMakefile</span></tt> classes. The build system contains +other Makefile classes, for example to build programs or to call other +Makefiles in sub-directories.</p> +<p>After running the script (using the Python interpreter the extension module is +being created for) the generated C++ code and <tt class="docutils literal"><span class="pre">Makefile</span></tt> will be in the +current directory.</p> +<p>To compile and install the extension module, just run the following +commands <a class="footnote-reference" href="#id6" id="id3">[3]</a>:</p> +<div class="highlight-python"><pre>make +make install</pre> +</div> +<p>That’s all there is to it.</p> +<p>See <a class="reference external" href="distutils.html#ref-distutils"><em>Building Your Extension with distutils</em></a> for an example of how to build this example using +distutils.</p> +<table class="docutils footnote" frame="void" id="id4" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>All SIP directives start with a <tt class="docutils literal"><span class="pre">%</span></tt> as the first non-whitespace +character of a line.</td></tr> +</tbody> +</table> +<table class="docutils footnote" frame="void" id="id5" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>SIP includes many code directives like this. They differ in where the +supplied code is placed by SIP in the generated code.</td></tr> +</tbody> +</table> +<table class="docutils footnote" frame="void" id="id6" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id3">[3]</a></td><td>On Windows you might run <tt class="docutils literal"><span class="pre">nmake</span></tt> or <tt class="docutils literal"><span class="pre">mingw32-make</span></tt> instead.</td></tr> +</tbody> +</table> +</div> +<div class="section" id="id7"> +<h2>A Simple C Example<a class="headerlink" href="#id7" title="Permalink to this headline">¶</a></h2> +<p>Let’s now look at a very similar example of wrapping a fictional C library:</p> +<div class="highlight-python"><pre>/* Define the interface to the word library. */ + +struct Word { + const char *the_word; +}; + +struct Word *create_word(const char *w); +char *reverse(struct Word *word);</pre> +</div> +<p>The corresponding SIP specification file would then look something like this:</p> +<div class="highlight-python"><pre>/* Define the SIP wrapper to the word library. */ + +%CModule word 0 + +struct Word { + +%TypeHeaderCode +#include <word.h> +%End + + const char *the_word; +}; + +struct Word *create_word(const char *w) /Factory/; +char *reverse(struct Word *word);</pre> +</div> +<p>Again, let’s look at the differences between the two files.</p> +<blockquote> +<ul class="simple"> +<li>The <a class="reference external" href="directives.html#directive-%CModule"><tt class="xref docutils literal"><span class="pre">%CModule</span></tt></a> directive has been added. This has the same +syntax as the <a class="reference external" href="directives.html#directive-%Module"><tt class="xref docutils literal"><span class="pre">%Module</span></tt></a> directive used in the previous example +but tells SIP that the library being wrapped is implemented in C rather +than C++.</li> +<li>The <a class="reference external" href="directives.html#directive-%TypeHeaderCode"><tt class="xref docutils literal"><span class="pre">%TypeHeaderCode</span></tt></a> directive has been added.</li> +<li>The <a class="reference external" href="annotations.html#fanno-Factory"><tt class="xref docutils literal"><span class="pre">Factory</span></tt></a> annotation has been added to the <tt class="docutils literal"><span class="pre">create_word()</span></tt> +function. This tells SIP that a newly created structure is being +returned and it is owned by Python.</li> +</ul> +</blockquote> +<p>The <tt class="docutils literal"><span class="pre">configure.py</span></tt> build system script described in the previous example can +be used for this example without change.</p> +</div> +<div class="section" id="a-more-complex-c-example"> +<h2>A More Complex C++ Example<a class="headerlink" href="#a-more-complex-c-example" title="Permalink to this headline">¶</a></h2> +<p>In this last example we will wrap a fictional C++ library that contains a class +that is derived from a Qt class. This will demonstrate how SIP allows a class +hierarchy to be split across multiple Python extension modules, and will +introduce SIP’s versioning system.</p> +<p>The library contains a single C++ class called <tt class="docutils literal"><span class="pre">Hello</span></tt> which is derived from +Qt’s <tt class="docutils literal"><span class="pre">QLabel</span></tt> class. It behaves just like <tt class="docutils literal"><span class="pre">QLabel</span></tt> except that the text +in the label is hard coded to be <tt class="docutils literal"><span class="pre">Hello</span> <span class="pre">World</span></tt>. To make the example more +interesting we’ll also say that the library only supports Qt v4.2 and later, +and also includes a function called <tt class="docutils literal"><span class="pre">setDefault()</span></tt> that is not implemented +in the Windows version of the library.</p> +<p>The <tt class="docutils literal"><span class="pre">hello.h</span></tt> header file looks something like this:</p> +<div class="highlight-python"><pre>// Define the interface to the hello library. + +#include <qlabel.h> +#include <qwidget.h> +#include <qstring.h> + +class Hello : public QLabel { + // This is needed by the Qt Meta-Object Compiler. + Q_OBJECT + +public: + Hello(QWidget *parent = 0); + +private: + // Prevent instances from being copied. + Hello(const Hello &); + Hello &operator=(const Hello &); +}; + +#if !defined(Q_OS_WIN) +void setDefault(const QString &def); +#endif</pre> +</div> +<p>The corresponding SIP specification file would then look something like this:</p> +<div class="highlight-python"><pre>// Define the SIP wrapper to the hello library. + +%Module hello 0 + +%Import QtGui/QtGuimod.sip + +%If (Qt_4_2_0 -) + +class Hello : QLabel { + +%TypeHeaderCode +#include <hello.h> +%End + +public: + Hello(QWidget *parent /TransferThis/ = 0); + +private: + Hello(const Hello &); +}; + +%If (!WS_WIN) +void setDefault(const QString &def); +%End + +%End</pre> +</div> +<p>Again we look at the differences, but we’ll skip those that we’ve looked at in +previous examples.</p> +<blockquote> +<ul class="simple"> +<li>The <a class="reference external" href="directives.html#directive-%Import"><tt class="xref docutils literal"><span class="pre">%Import</span></tt></a> directive has been added to specify that we are +extending the class hierarchy defined in the file <tt class="docutils literal"><span class="pre">QtGui/QtGuimod.sip</span></tt>. +This file is part of PyQt. The build system will take care of finding +the file’s exact location.</li> +<li>The <a class="reference external" href="directives.html#directive-%If"><tt class="xref docutils literal"><span class="pre">%If</span></tt></a> directive has been added to specify that everything +<a class="footnote-reference" href="#id11" id="id8">[4]</a> up to the matching <a class="reference external" href="directives.html#directive-%End"><tt class="xref docutils literal"><span class="pre">%End</span></tt></a> directive only applies to Qt +v4.2 and later. <tt class="docutils literal"><span class="pre">Qt_4_2_0</span></tt> is a <em>tag</em> defined in <tt class="docutils literal"><span class="pre">QtCoremod.sip</span></tt> +<a class="footnote-reference" href="#id12" id="id9">[5]</a> using the <a class="reference external" href="directives.html#directive-%Timeline"><tt class="xref docutils literal"><span class="pre">%Timeline</span></tt></a> directive. <a class="reference external" href="directives.html#directive-%Timeline"><tt class="xref docutils literal"><span class="pre">%Timeline</span></tt></a> +is used to define a tag for each version of a library’s API you are +wrapping allowing you to maintain all the different versions in a single +SIP specification. The build system provides support to <tt class="docutils literal"><span class="pre">configure.py</span></tt> +scripts for working out the correct tags to use according to which +version of the library is actually installed.</li> +<li>The <tt class="docutils literal"><span class="pre">public</span></tt> keyword used in defining the super-classes has been +removed. This is not supported by SIP.</li> +<li>The <a class="reference external" href="annotations.html#aanno-TransferThis"><tt class="xref docutils literal"><span class="pre">TransferThis</span></tt></a> annotation has been added to the constructor’s +argument. It specifies that if the argument is not 0 (i.e. the <tt class="docutils literal"><span class="pre">Hello</span></tt> +instance being constructed has a parent) then ownership of the instance +is transferred from Python to C++. It is needed because Qt maintains +objects (i.e. instances derived from the <tt class="docutils literal"><span class="pre">QObject</span></tt> class) in a +hierachy. When an object is destroyed all of its children are also +automatically destroyed. It is important, therefore, that the Python +garbage collector doesn’t also try and destroy them. This is covered in +more detail in <a class="reference internal" href="#ref-object-ownership"><em>Ownership of Objects</em></a>. SIP provides many other +annotations that can be applied to arguments, functions and classes. +Multiple annotations are separated by commas. Annotations may have +values.</li> +<li>The <tt class="docutils literal"><span class="pre">=</span></tt> operator has been removed. This operator is not supported by +SIP.</li> +<li>The <a class="reference external" href="directives.html#directive-%If"><tt class="xref docutils literal"><span class="pre">%If</span></tt></a> directive has been added to specify that everything +up to the matching <a class="reference external" href="directives.html#directive-%End"><tt class="xref docutils literal"><span class="pre">%End</span></tt></a> directive does not apply to Windows. +<tt class="docutils literal"><span class="pre">WS_WIN</span></tt> is another tag defined by PyQt, this time using the +<a class="reference external" href="directives.html#directive-%Platforms"><tt class="xref docutils literal"><span class="pre">%Platforms</span></tt></a> directive. Tags defined by the +<a class="reference external" href="directives.html#directive-%Platforms"><tt class="xref docutils literal"><span class="pre">%Platforms</span></tt></a> directive are mutually exclusive, i.e. only one +may be valid at a time <a class="footnote-reference" href="#id13" id="id10">[6]</a>.</li> +</ul> +</blockquote> +<p>One question you might have at this point is why bother to define the private +copy constructor when it can never be called from Python? The answer is to +prevent the automatic generation of a public copy constructor.</p> +<p>We now look at the <tt class="docutils literal"><span class="pre">configure.py</span></tt> script. This is a little different to the +script in the previous examples for two related reasons.</p> +<p>Firstly, PyQt includes a pure Python module called <tt class="docutils literal"><span class="pre">pyqtconfig</span></tt> that extends +the SIP build system for modules, like our example, that build on top of PyQt. +It deals with the details of which version of Qt is being used (i.e. it +determines what the correct tags are) and where it is installed. This is +called a module’s configuration module.</p> +<p>Secondly, we generate a configuration module (called <tt class="docutils literal"><span class="pre">helloconfig</span></tt>) for our +own <tt class="docutils literal"><span class="pre">hello</span></tt> module. There is no need to do this, but if there is a chance +that somebody else might want to extend your C++ library then it would make +life easier for them.</p> +<p>Now we have two scripts. First the <tt class="docutils literal"><span class="pre">configure.py</span></tt> script:</p> +<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span> +<span class="kn">import</span> <span class="nn">sipconfig</span> +<span class="kn">from</span> <span class="nn">PyQt4</span> <span class="kn">import</span> <span class="n">pyqtconfig</span> + +<span class="c"># The name of the SIP build file generated by SIP and used by the build</span> +<span class="c"># system.</span> +<span class="n">build_file</span> <span class="o">=</span> <span class="s">"hello.sbf"</span> + +<span class="c"># Get the PyQt configuration information.</span> +<span class="n">config</span> <span class="o">=</span> <span class="n">pyqtconfig</span><span class="o">.</span><span class="n">Configuration</span><span class="p">()</span> + +<span class="c"># Get the extra SIP flags needed by the imported PyQt modules. Note that</span> +<span class="c"># this normally only includes those flags (-x and -t) that relate to SIP's</span> +<span class="c"># versioning system.</span> +<span class="n">pyqt_sip_flags</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">pyqt_sip_flags</span> + +<span class="c"># Run SIP to generate the code. Note that we tell SIP where to find the qt</span> +<span class="c"># module's specification files using the -I flag.</span> +<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s">" "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">config</span><span class="o">.</span><span class="n">sip_bin</span><span class="p">,</span> <span class="s">"-c"</span><span class="p">,</span> <span class="s">"."</span><span class="p">,</span> <span class="s">"-b"</span><span class="p">,</span> <span class="n">build_file</span><span class="p">,</span> <span class="s">"-I"</span><span class="p">,</span> <span class="n">config</span><span class="o">.</span><span class="n">pyqt_sip_dir</span><span class="p">,</span> <span class="n">pyqt_sip_flags</span><span class="p">,</span> <span class="s">"hello.sip"</span><span class="p">]))</span> + +<span class="c"># We are going to install the SIP specification file for this module and</span> +<span class="c"># its configuration module.</span> +<span class="n">installs</span> <span class="o">=</span> <span class="p">[]</span> + +<span class="n">installs</span><span class="o">.</span><span class="n">append</span><span class="p">([</span><span class="s">"hello.sip"</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">default_sip_dir</span><span class="p">,</span> <span class="s">"hello"</span><span class="p">)])</span> + +<span class="n">installs</span><span class="o">.</span><span class="n">append</span><span class="p">([</span><span class="s">"helloconfig.py"</span><span class="p">,</span> <span class="n">config</span><span class="o">.</span><span class="n">default_mod_dir</span><span class="p">])</span> + +<span class="c"># Create the Makefile. The QtGuiModuleMakefile class provided by the</span> +<span class="c"># pyqtconfig module takes care of all the extra preprocessor, compiler and</span> +<span class="c"># linker flags needed by the Qt library.</span> +<span class="n">makefile</span> <span class="o">=</span> <span class="n">pyqtconfig</span><span class="o">.</span><span class="n">QtGuiModuleMakefile</span><span class="p">(</span> + <span class="n">configuration</span><span class="o">=</span><span class="n">config</span><span class="p">,</span> + <span class="n">build_file</span><span class="o">=</span><span class="n">build_file</span><span class="p">,</span> + <span class="n">installs</span><span class="o">=</span><span class="n">installs</span> +<span class="p">)</span> + +<span class="c"># Add the library we are wrapping. The name doesn't include any platform</span> +<span class="c"># specific prefixes or extensions (e.g. the "lib" prefix on UNIX, or the</span> +<span class="c"># ".dll" extension on Windows).</span> +<span class="n">makefile</span><span class="o">.</span><span class="n">extra_libs</span> <span class="o">=</span> <span class="p">[</span><span class="s">"hello"</span><span class="p">]</span> + +<span class="c"># Generate the Makefile itself.</span> +<span class="n">makefile</span><span class="o">.</span><span class="n">generate</span><span class="p">()</span> + +<span class="c"># Now we create the configuration module. This is done by merging a Python</span> +<span class="c"># dictionary (whose values are normally determined dynamically) with a</span> +<span class="c"># (static) template.</span> +<span class="n">content</span> <span class="o">=</span> <span class="p">{</span> + <span class="c"># Publish where the SIP specifications for this module will be</span> + <span class="c"># installed.</span> + <span class="s">"hello_sip_dir"</span><span class="p">:</span> <span class="n">config</span><span class="o">.</span><span class="n">default_sip_dir</span><span class="p">,</span> + + <span class="c"># Publish the set of SIP flags needed by this module. As these are the</span> + <span class="c"># same flags needed by the qt module we could leave it out, but this</span> + <span class="c"># allows us to change the flags at a later date without breaking</span> + <span class="c"># scripts that import the configuration module.</span> + <span class="s">"hello_sip_flags"</span><span class="p">:</span> <span class="n">pyqt_sip_flags</span> +<span class="p">}</span> + +<span class="c"># This creates the helloconfig.py module from the helloconfig.py.in</span> +<span class="c"># template and the dictionary.</span> +<span class="n">sipconfig</span><span class="o">.</span><span class="n">create_config_module</span><span class="p">(</span><span class="s">"helloconfig.py"</span><span class="p">,</span> <span class="s">"helloconfig.py.in"</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span> +</pre></div> +</div> +<p>Next we have the <tt class="docutils literal"><span class="pre">helloconfig.py.in</span></tt> template script:</p> +<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">PyQt4</span> <span class="kn">import</span> <span class="n">pyqtconfig</span> + +<span class="c"># These are installation specific values created when Hello was configured.</span> +<span class="c"># The following line will be replaced when this template is used to create</span> +<span class="c"># the final configuration module.</span> +<span class="c"># @SIP_CONFIGURATION@</span> + +<span class="k">class</span> <span class="nc">Configuration</span><span class="p">(</span><span class="n">pyqtconfig</span><span class="o">.</span><span class="n">Configuration</span><span class="p">):</span> + <span class="sd">"""The class that represents Hello configuration values.</span> +<span class="sd"> """</span> + <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sub_cfg</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> + <span class="sd">"""Initialise an instance of the class.</span> + +<span class="sd"> sub_cfg is the list of sub-class configurations. It should be None</span> +<span class="sd"> when called normally.</span> +<span class="sd"> """</span> + <span class="c"># This is all standard code to be copied verbatim except for the</span> + <span class="c"># name of the module containing the super-class.</span> + <span class="k">if</span> <span class="n">sub_cfg</span><span class="p">:</span> + <span class="n">cfg</span> <span class="o">=</span> <span class="n">sub_cfg</span> + <span class="k">else</span><span class="p">:</span> + <span class="n">cfg</span> <span class="o">=</span> <span class="p">[]</span> + + <span class="n">cfg</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">_pkg_config</span><span class="p">)</span> + + <span class="n">pyqtconfig</span><span class="o">.</span><span class="n">Configuration</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cfg</span><span class="p">)</span> + +<span class="k">class</span> <span class="nc">HelloModuleMakefile</span><span class="p">(</span><span class="n">pyqtconfig</span><span class="o">.</span><span class="n">QtGuiModuleMakefile</span><span class="p">):</span> + <span class="sd">"""The Makefile class for modules that %Import hello.</span> +<span class="sd"> """</span> + <span class="k">def</span> <span class="nf">finalise</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> + <span class="sd">"""Finalise the macros.</span> +<span class="sd"> """</span> + <span class="c"># Make sure our C++ library is linked.</span> + <span class="bp">self</span><span class="o">.</span><span class="n">extra_libs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">"hello"</span><span class="p">)</span> + + <span class="c"># Let the super-class do what it needs to.</span> + <span class="n">pyqtconfig</span><span class="o">.</span><span class="n">QtGuiModuleMakefile</span><span class="o">.</span><span class="n">finalise</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> +</pre></div> +</div> +<p>Again, we hope that the scripts are self documenting.</p> +<table class="docutils footnote" frame="void" id="id11" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id8">[4]</a></td><td>Some parts of a SIP specification aren’t subject to version control.</td></tr> +</tbody> +</table> +<table class="docutils footnote" frame="void" id="id12" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id9">[5]</a></td><td>Actually in <tt class="docutils literal"><span class="pre">versions.sip</span></tt>. PyQt uses the <a class="reference external" href="directives.html#directive-%Include"><tt class="xref docutils literal"><span class="pre">%Include</span></tt></a> +directive to split the SIP specification for Qt across a large number of +separate <tt class="docutils literal"><span class="pre">.sip</span></tt> files.</td></tr> +</tbody> +</table> +<table class="docutils footnote" frame="void" id="id13" rules="none"> +<colgroup><col class="label" /><col /></colgroup> +<tbody valign="top"> +<tr><td class="label"><a class="fn-backref" href="#id10">[6]</a></td><td>Tags can also be defined by the <a class="reference external" href="directives.html#directive-%Feature"><tt class="xref docutils literal"><span class="pre">%Feature</span></tt></a> directive. These +tags are not mutually exclusive, i.e. any number may be valid at a time.</td></tr> +</tbody> +</table> +</div> +<div class="section" id="ownership-of-objects"> +<span id="ref-object-ownership"></span><h2>Ownership of Objects<a class="headerlink" href="#ownership-of-objects" title="Permalink to this headline">¶</a></h2> +<p>When a C++ instance is wrapped a corresponding Python object is created. The +Python object behaves as you would expect in regard to garbage collection - it +is garbage collected when its reference count reaches zero. What then happens +to the corresponding C++ instance? The obvious answer might be that the +instance’s destructor is called. However the library API may say that when the +instance is passed to a particular function, the library takes ownership of the +instance, i.e. responsibility for calling the instance’s destructor is +transferred from the SIP generated module to the library.</p> +<p>Ownership of an instance may also be associated with another instance. The +implication being that the owned instance will automatically be destroyed if +the owning instance is destroyed. SIP keeps track of these relationships to +ensure that Python’s cyclic garbage collector can detect and break any +reference cycles between the owning and owned instances. The association is +implemented as the owning instance taking a reference to the owned instance.</p> +<p>The TransferThis, Transfer and TransferBack annotations are used to specify +where, and it what direction, transfers of ownership happen. It is very +important that these are specified correctly to avoid crashes (where both +Python and C++ call the destructor) and memory leaks (where neither Python and +C++ call the destructor).</p> +<p>This applies equally to C structures where the structure is returned to the +heap using the <tt class="docutils literal"><span class="pre">free()</span></tt> function.</p> +<p>See also <a title="sipTransferTo" class="reference external" href="c_api.html#sipTransferTo"><tt class="xref docutils literal"><span class="pre">sipTransferTo()</span></tt></a>, <a title="sipTransferBack" class="reference external" href="c_api.html#sipTransferBack"><tt class="xref docutils literal"><span class="pre">sipTransferBack()</span></tt></a> and +<a title="sipTransferBreak" class="reference external" href="c_api.html#sipTransferBreak"><tt class="xref docutils literal"><span class="pre">sipTransferBreak()</span></tt></a>.</p> +</div> +<div class="section" id="types-and-meta-types"> +<span id="ref-types-metatypes"></span><h2>Types and Meta-types<a class="headerlink" href="#types-and-meta-types" title="Permalink to this headline">¶</a></h2> +<p>Every Python object (with the exception of the <tt class="xref docutils literal"><span class="pre">object</span></tt> object itself) +has a meta-type and at least one super-type. By default an object’s meta-type +is the meta-type of its first super-type.</p> +<p>SIP implements two super-types, <tt class="xref docutils literal"><span class="pre">sip.simplewrapper</span></tt> and +<a title="sip.wrapper" class="reference external" href="python_api.html#sip.wrapper"><tt class="xref docutils literal"><span class="pre">sip.wrapper</span></tt></a>, and a meta-type, <a title="sip.wrappertype" class="reference external" href="python_api.html#sip.wrappertype"><tt class="xref docutils literal"><span class="pre">sip.wrappertype</span></tt></a>.</p> +<p><tt class="xref docutils literal"><span class="pre">sip.simplewrapper</span></tt> is the super-type of <a title="sip.wrapper" class="reference external" href="python_api.html#sip.wrapper"><tt class="xref docutils literal"><span class="pre">sip.wrapper</span></tt></a>. The +super-type of <tt class="xref docutils literal"><span class="pre">sip.simplewrapper</span></tt> is <tt class="xref docutils literal"><span class="pre">object</span></tt>.</p> +<p><a title="sip.wrappertype" class="reference external" href="python_api.html#sip.wrappertype"><tt class="xref docutils literal"><span class="pre">sip.wrappertype</span></tt></a> is the meta-type of both <tt class="xref docutils literal"><span class="pre">sip.simplewrapper</span></tt> +and <a title="sip.wrapper" class="reference external" href="python_api.html#sip.wrapper"><tt class="xref docutils literal"><span class="pre">sip.wrapper</span></tt></a>. The super-type of <a title="sip.wrappertype" class="reference external" href="python_api.html#sip.wrappertype"><tt class="xref docutils literal"><span class="pre">sip.wrappertype</span></tt></a> is +<tt class="xref docutils literal"><span class="pre">type</span></tt>.</p> +<p><a title="sip.wrapper" class="reference external" href="python_api.html#sip.wrapper"><tt class="xref docutils literal"><span class="pre">sip.wrapper</span></tt></a> supports the concept of object ownership described in +<a class="reference internal" href="#ref-object-ownership"><em>Ownership of Objects</em></a> and, by default, is the super-type of all the types +that SIP generates.</p> +<p><tt class="xref docutils literal"><span class="pre">sip.simplewrapper</span></tt> does not support the concept of object ownership but +SIP generated types that are sub-classed from it have Python objects that take +less memory.</p> +<p>SIP allows a class’s meta-type and super-type to be explicitly specified using +the <a class="reference external" href="annotations.html#canno-Metatype"><tt class="xref docutils literal"><span class="pre">Metatype</span></tt></a> and <a class="reference external" href="annotations.html#canno-Supertype"><tt class="xref docutils literal"><span class="pre">Supertype</span></tt></a> class annotations.</p> +<p>SIP also allows the default meta-type and super-type to be changed for a module +using the <a class="reference external" href="directives.html#directive-%DefaultMetatype"><tt class="xref docutils literal"><span class="pre">%DefaultMetatype</span></tt></a> and <a class="reference external" href="directives.html#directive-%DefaultSupertype"><tt class="xref docutils literal"><span class="pre">%DefaultSupertype</span></tt></a> +directives. Unlike the default super-type, the default meta-type is inherited +by importing modules.</p> +<p>If you want to use your own meta-type or super-type then they must be +sub-classed from one of the SIP provided types. Your types must be registered +using <a title="sipRegisterPyType" class="reference external" href="c_api.html#sipRegisterPyType"><tt class="xref docutils literal"><span class="pre">sipRegisterPyType()</span></tt></a>. This is normally done in code specified +using the <a class="reference external" href="directives.html#directive-%InitialisationCode"><tt class="xref docutils literal"><span class="pre">%InitialisationCode</span></tt></a> directive.</p> +<p>As an example, PyQt4 uses <a class="reference external" href="directives.html#directive-%DefaultMetatype"><tt class="xref docutils literal"><span class="pre">%DefaultMetatype</span></tt></a> to specify a new +meta-type that handles the interaction with Qt’s own meta-type system. It also +uses <a class="reference external" href="directives.html#directive-%DefaultSupertype"><tt class="xref docutils literal"><span class="pre">%DefaultSupertype</span></tt></a> to specify that the smaller +<tt class="xref docutils literal"><span class="pre">sip.simplewrapper</span></tt> super-type is normally used. Finally it uses +<a class="reference external" href="annotations.html#canno-Supertype"><tt class="xref docutils literal"><span class="pre">Supertype</span></tt></a> as an annotation of the <tt class="docutils literal"><span class="pre">QObject</span></tt> class to override the +default and use <a title="sip.wrapper" class="reference external" href="python_api.html#sip.wrapper"><tt class="xref docutils literal"><span class="pre">sip.wrapper</span></tt></a> as the super-type so that the parent/child +relationships of <tt class="docutils literal"><span class="pre">QObject</span></tt> instances are properly maintained.</p> +</div> +<div class="section" id="lazy-type-attributes"> +<span id="ref-lazy-type-attributes"></span><h2>Lazy Type Attributes<a class="headerlink" href="#lazy-type-attributes" title="Permalink to this headline">¶</a></h2> +<p>Instead of populating a wrapped type’s dictionary with its attributes (or +descriptors for those attributes) SIP only creates objects for those attributes +when they are actually needed. This is done to reduce the memory footprint and +start up time when used to wrap large libraries with hundreds of classes and +tens of thousands of attributes.</p> +<p>SIP allows you to extend the handling of lazy attributes to your own attribute +types by allowing you to register an attribute getter handler (using +<a title="sipRegisterAttributeGetter" class="reference external" href="c_api.html#sipRegisterAttributeGetter"><tt class="xref docutils literal"><span class="pre">sipRegisterAttributeGetter()</span></tt></a>). This will be called just before a +type’s dictionary is accessed for the first time.</p> +</div> +<div class="section" id="support-for-python-s-buffer-interface"> +<h2>Support for Python’s Buffer Interface<a class="headerlink" href="#support-for-python-s-buffer-interface" title="Permalink to this headline">¶</a></h2> +<p>SIP supports Python’s buffer interface in that whenever C/C++ requires a +<tt class="docutils literal"><span class="pre">char</span></tt> or <tt class="docutils literal"><span class="pre">char</span> <span class="pre">*</span></tt> type then any Python type that supports the buffer +interface (including ordinary Python strings) can be used.</p> +<p>If a buffer is made up of a number of segments then all but the first will be +ignored.</p> +</div> +<div class="section" id="support-for-wide-characters"> +<h2>Support for Wide Characters<a class="headerlink" href="#support-for-wide-characters" title="Permalink to this headline">¶</a></h2> +<p>SIP v4.6 introduced support for wide characters (i.e. the <tt class="docutils literal"><span class="pre">wchar_t</span></tt> type). +Python’s C API includes support for converting between unicode objects and wide +character strings and arrays. When converting from a unicode object to wide +characters SIP creates the string or array on the heap (using memory allocated +using <a title="sipMalloc" class="reference external" href="c_api.html#sipMalloc"><tt class="xref docutils literal"><span class="pre">sipMalloc()</span></tt></a>). This then raises the problem of how this memory +is subsequently freed.</p> +<p>The following describes how SIP handles this memory in the different situations +where this is an issue.</p> +<blockquote> +<ul class="simple"> +<li>When a wide string or array is passed to a function or method then the +memory is freed (using <a title="sipFree" class="reference external" href="c_api.html#sipFree"><tt class="xref docutils literal"><span class="pre">sipFree()</span></tt></a>) after than function or method +returns.</li> +<li>When a wide string or array is returned from a virtual method then SIP +does not free the memory until the next time the method is called.</li> +<li>When an assignment is made to a wide string or array instance variable +then SIP does not first free the instance’s current string or array.</li> +</ul> +</blockquote> +</div> +<div class="section" id="the-python-global-interpreter-lock"> +<span id="ref-gil"></span><h2>The Python Global Interpreter Lock<a class="headerlink" href="#the-python-global-interpreter-lock" title="Permalink to this headline">¶</a></h2> +<p>Python’s Global Interpretor Lock (GIL) must be acquired before calls can be +made to the Python API. It should also be released when a potentially +blocking call to C/C++ library is made in order to allow other Python threads +to be executed. In addition, some C/C++ libraries may implement their own +locking strategies that conflict with the GIL causing application deadlocks. +SIP provides ways of specifying when the GIL is released and acquired to +ensure that locking problems can be avoided.</p> +<p>SIP always ensures that the GIL is acquired before making calls to the Python +API. By default SIP does not release the GIL when making calls to the C/C++ +library being wrapped. The <a class="reference external" href="annotations.html#fanno-ReleaseGIL"><tt class="xref docutils literal"><span class="pre">ReleaseGIL</span></tt></a> annotation can be used to +override this behaviour when required.</p> +<p>If SIP is given the <a class="reference external" href="command_line.html#cmdoption-sip-g"><em class="xref">-g</em></a> command line option then the default +behaviour is changed and SIP releases the GIL every time is makes calls to the +C/C++ library being wrapped. The <a class="reference external" href="annotations.html#fanno-HoldGIL"><tt class="xref docutils literal"><span class="pre">HoldGIL</span></tt></a> annotation can be used to +override this behaviour when required.</p> +</div> +<div class="section" id="managing-incompatible-apis"> +<span id="ref-incompat-apis"></span><h2>Managing Incompatible APIs<a class="headerlink" href="#managing-incompatible-apis" title="Permalink to this headline">¶</a></h2> +<p> +<span class="versionmodified">New in version 4.9.</span></p> +<p>Sometimes it is necessary to change the way something is wrapped in a way that +introduces an incompatibility. For example a new feature of Python may +suggest that something may be wrapped in a different way to exploit that +feature.</p> +<p>SIP’s <a class="reference external" href="directives.html#directive-%Feature"><tt class="xref docutils literal"><span class="pre">%Feature</span></tt></a> directive could be used to provide two different +implementations. However this would mean that the choice between the two +implementations would have to be made when building the generated module +potentially causing all sorts of deployment problems. It may also require +applications to work out which implementation was available and to change +their behaviour accordingly.</p> +<p>Instead SIP provides limited support for providing multiple implementations +(of classes, mapped types and functions) that can be selected by an +application at run-time. It is then up to the application developer how they +want to manage the migration from the old API to the new, incompatible API.</p> +<p>This support is implemented in three parts.</p> +<p>Firstly the <a class="reference external" href="directives.html#directive-%API"><tt class="xref docutils literal"><span class="pre">%API</span></tt></a> directive is used to define the name of an API +and its default version number. The default version number is the one used if +an application doesn’t explicitly set the version number to use.</p> +<p>Secondly the <a class="reference external" href="annotations.html#canno-API"><tt class="xref docutils literal"><span class="pre">API</span> <span class="pre">class</span></tt></a>, <a class="reference external" href="annotations.html#manno-API"><tt class="xref docutils literal"><span class="pre">mapped</span> <span class="pre">type</span></tt></a> or +<a class="reference external" href="annotations.html#fanno-API"><tt class="xref docutils literal"><span class="pre">function</span></tt></a> annotation is applied accordingly to specify the API +and range of version numbers that a particular class, mapped type or function +implementation should be enabled for.</p> +<p>Finally the application calls <a title="sip.setapi" class="reference external" href="python_api.html#sip.setapi"><tt class="xref docutils literal"><span class="pre">sip.setapi()</span></tt></a> to specify the version number +of the API that should be enabled. This call must be made before any module +that has multiple implementations is imported for the first time.</p> +<p>Note this mechanism is not intended as a way or providing equally valid +alternative APIs. For example:</p> +<div class="highlight-python"><pre>%API MyAPI 1 + +class Foo +{ +public: + void bar(); +}; + +class Baz : Foo +{ +public: + void bar() /API=MyAPI:2-/; +};</pre> +</div> +<p>If the following Python code is executed then an exception will be raised:</p> +<div class="highlight-python"><div class="highlight"><pre><span class="n">b</span> <span class="o">=</span> <span class="n">Baz</span><span class="p">()</span> +<span class="n">b</span><span class="o">.</span><span class="n">bar</span><span class="p">()</span> +</pre></div> +</div> +<p>This is because when version 1 of the <em>MyAPI</em> API (the default) is enabled +there is no <em>Baz.bar()</em> implementation and <em>Foo.bar()</em> will not be called +instead as might be expected.</p> +</div> +</div> + + + </div> + </div> + </div> + <div class="sphinxsidebar"> + <div class="sphinxsidebarwrapper"> + <h3><a href="index.html">Table Of Contents</a></h3> + <ul> +<li><a class="reference external" href="#">Using SIP</a><ul> +<li><a class="reference external" href="#a-simple-c-example">A Simple C++ Example</a></li> +<li><a class="reference external" href="#id7">A Simple C Example</a></li> +<li><a class="reference external" href="#a-more-complex-c-example">A More Complex C++ Example</a></li> +<li><a class="reference external" href="#ownership-of-objects">Ownership of Objects</a></li> +<li><a class="reference external" href="#types-and-meta-types">Types and Meta-types</a></li> +<li><a class="reference external" href="#lazy-type-attributes">Lazy Type Attributes</a></li> +<li><a class="reference external" href="#support-for-python-s-buffer-interface">Support for Python’s Buffer Interface</a></li> +<li><a class="reference external" href="#support-for-wide-characters">Support for Wide Characters</a></li> +<li><a class="reference external" href="#the-python-global-interpreter-lock">The Python Global Interpreter Lock</a></li> +<li><a class="reference external" href="#managing-incompatible-apis">Managing Incompatible APIs</a></li> +</ul> +</li> +</ul> + + <h4>Previous topic</h4> + <p class="topless"><a href="installation.html" + title="previous chapter">Installation</a></p> + <h4>Next topic</h4> + <p class="topless"><a href="command_line.html" + title="next chapter">The SIP Command Line</a></p> + <div id="searchbox" style="display: none"> + <h3>Quick search</h3> + <form class="search" action="search.html" method="get"> + <input type="text" name="q" size="18" /> + <input type="submit" value="Go" /> + <input type="hidden" name="check_keywords" value="yes" /> + <input type="hidden" name="area" value="default" /> + </form> + <p class="searchtip" style="font-size: 90%"> + Enter search terms or a module, class or function name. + </p> + </div> + <script type="text/javascript">$('#searchbox').show(0);</script> + </div> + </div> + <div class="clearer"></div> + </div> + <div class="related"> + <h3>Navigation</h3> + <ul> + <li class="right" style="margin-right: 10px"> + <a href="genindex.html" title="General Index" + >index</a></li> + <li class="right" > + <a href="modindex.html" title="Global Module Index" + >modules</a> |</li> + <li class="right" > + <a href="command_line.html" title="The SIP Command Line" + >next</a> |</li> + <li class="right" > + <a href="installation.html" title="Installation" + >previous</a> |</li> + <li><a href="index.html">SIP 4.10.5 Reference Guide</a> »</li> + </ul> + </div> + <div class="footer"> + © Copyright 2010 Riverbank Computing Limited. + Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.4. + </div> + </body> +</html>
\ No newline at end of file |