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.

342 lines
15 KiB

<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.61 (Macintosh; I; PPC) [Netscape]">
<title>Sharing Declarations Between Pyrex Modules</title></head>
<body>
<h1>
<hr width="100%">Sharing Declarations Between Pyrex Modules
<hr width="100%"></h1>
This section describes a new set of facilities introduced in Pyrex 0.8
for making C declarations, functions and extension types in one Pyrex module available
for use in another Pyrex module. These facilities are closely modelled on
the Python import mechanism, and can be thought of as a compile-time version
of it.
<h2><a class="mozTocH2" name="mozTocId699652"></a> Contents</h2><ul id="mozToc"><!--mozToc h2 1 h3 2--><li><a href="#mozTocId989010"> Definition and Implementation files</a><ul><li><a href="#mozTocId411233"> What a Definition File contains</a></li><li><a href="#mozTocId20347"> What an Implementation File contains</a></li></ul></li><li><a href="#mozTocId950993"> The <span style="font-family: monospace;">cimport</span> statement</a><ul><li><a href="#mozTocId559554"> Search paths for definition files</a></li><li><a href="#mozTocId478514"> Using <span style="font-family: monospace;">cimport</span> to resolve naming
conflicts</a></li></ul></li><li><a href="#mozTocId937218">Sharing C Functions</a></li><li><a href="#mozTocId825278">Sharing Extension Types</a></li><li><a href="#mozTocId144977">Circular cimports</a></li></ul>
<h2><a class="mozTocH2" name="mozTocId989010"></a> <a name="DefAndImpFiles"></a>Definition and Implementation files</h2>
A Pyrex module can be split into two parts: a <i>definition file</i> with
a <tt>.pxd</tt> suffix, containing C declarations that are to be available
to other Pyrex modules, and an <i>implementation file</i> with a <tt>.pyx</tt>
suffix, containing everything else. When a module wants to use something
declared in another module's definition file, it imports it using the <a href="#CImportStatement"><b>cimport</b> statement</a>.
<h3><a class="mozTocH3" name="mozTocId411233"></a> <a name="WhatDefFileContains"></a>What a Definition File contains</h3>
A definition file can contain:
<ul>
<li> Any kind of C type declaration.</li>
<li> <b>extern</b> C function or variable declarations.</li><li>Declarations of C functions defined in the module.</li>
<li> The definition part of an extension type (<a href="#SharingExtensionTypes">see below</a>).</li>
</ul>
It cannot contain any non-extern C variable declarations.
<p>It cannot contain the implementations of any C or Python functions, or
any Python class definitions, or any executable statements. </p>
<blockquote>NOTE: You don't need to (and shouldn't) declare anything in a
declaration file <b>public</b> in order to make it available to other Pyrex
modules; its mere presence in a definition file does that. You only need a
public declaration if you want to make something available to external C code.</blockquote>
<h3><a class="mozTocH3" name="mozTocId20347"></a> <a name="WhatImpFileContains"></a>What an Implementation File contains</h3>
An implementation file can contain any kind of Pyrex statement, although
there are some restrictions on the implementation part of an extension type
if the corresponding definition file also defines that type (see below).
<h2><a class="mozTocH2" name="mozTocId950993"></a> <a name="CImportStatement"></a>The <tt>cimport</tt> statement</h2>
The <b>cimport</b> statement is used in a definition or implementation
file to gain access to names declared in another definition file. Its syntax
exactly parallels that of the normal Python import statement:
<blockquote><tt>cimport </tt><i>module</i><tt> [, </tt><i>module</i><tt>...]</tt></blockquote>
<blockquote><tt>from </tt><i>module</i><tt> cimport </tt><i>name</i><tt>
[as </tt><i>name</i><tt>] [, </tt><i>name</i><tt> [as </tt><i>name</i><tt>]
...]</tt></blockquote>
Here is an example. The file on the left is a definition file which exports
a C data type. The file on the right is an implementation file which imports
and uses it. <br>
&nbsp;
<table cellpadding="5" cols="2" width="100%">
<tbody>
<tr>
<td bgcolor="#ffcc00" width="40%"><b><tt>dishes.pxd</tt></b></td>
<td bgcolor="#5dbaca"><b><tt>restaurant.pyx</tt></b></td>
</tr>
<tr align="left" valign="top">
<td bgcolor="#ffcc18" width="40%"><tt>cdef enum otherstuff:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; sausage, eggs, lettuce</tt>
<p><tt>cdef struct spamdish:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; int oz_of_spam</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; otherstuff filler</tt></p>
</td>
<td bgcolor="#5dbaca"><tt>cimport dishes</tt> <br>
<tt>from dishes cimport spamdish</tt>
<p><tt>cdef void prepare(spamdish *d):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; d.oz_of_spam = 42</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; d.filler = dishes.sausage</tt> </p>
<p><tt>def serve():</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; cdef spamdish d</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; prepare(&amp;d)</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; print "%d oz spam, filler no. %d" % \</tt>
<br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (d.oz_of_spam,
d.filler)</tt></p>
</td>
</tr>
</tbody>
</table>
<p>It is important to understand that the <b>cimport</b> statement can <i>only</i>
be used to import C data types, C functions and variables, and extension
types. It cannot be used to import any Python objects, and (with one exception)
it doesn't imply any Python import at run time. If you want to refer to any
Python names from a module that you have cimported, you will have to include
a regular <b>import</b> statement for it as well. </p>
<p>The exception is that when you use <b>cimport</b> to import an extension
type, its type object is imported at run time and made available by the
name under which you imported it. Using <b>cimport</b> to import extension
types is covered in more detail <a href="#SharingExtensionTypes">below</a>.
</p>
<h3><a class="mozTocH3" name="mozTocId559554"></a> <a name="SearchPaths"></a>Search paths for definition files</h3>
When you <b>cimport</b> a module called <tt>modulename</tt>, the Pyrex
compiler searches for a file called <tt>modulename.pxd</tt> along the search
path for include files, as specified by <b>-I</b> command line options.
<p>Also, whenever you compile a file <tt>modulename.pyx</tt>, the corresponding
definition file <tt>modulename.pxd</tt> is first searched for along the
same path, and if found, it is processed before processing the <tt>.pyx</tt>
file. </p>
<h3><a class="mozTocH3" name="mozTocId478514"></a> <a name="ResolvingNamingConflicts"></a>Using cimport to resolve naming
conflicts</h3>
The cimport mechanism provides a clean and simple way to solve the problem
of wrapping external C functions with Python functions of the same name.
All you need to do is put the extern C declarations into a .pxd file for
an imaginary module, and cimport that module. You can then refer to the C
functions by qualifying them with the name of the module. Here's an example:
<br>
&nbsp;
<table cellpadding="5" cols="2" width="100%">
<tbody>
<tr>
<td bgcolor="#ffcc00" width="50%"><b><tt>c_lunch.pxd</tt></b></td>
<td bgcolor="#5dbaca"><b><tt>lunch.pyx</tt></b></td>
</tr>
<tr align="left" valign="top">
<td bgcolor="#ffcc18" width="50%"><tt>cdef extern from "lunch.h":</tt>
<br>
<tt>&nbsp;&nbsp;&nbsp; void eject_tomato(float)</tt></td>
<td bgcolor="#5dbaca"><tt>cimport c_lunch</tt>
<p><tt>def eject_tomato(float speed):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; c_lunch.eject_tomato(speed)</tt></p>
</td>
</tr>
</tbody>
</table>
<p>You don't need any <tt>c_lunch.pyx</tt> file, because the only things
defined in <tt>c_lunch.pxd</tt> are extern C entities. There won't be any
actual <tt>c_lunch</tt> module at run time, but that doesn't matter; the <tt>c_lunch.pxd</tt> file has done its job of providing an additional namespace at compile time.</p><h2><a class="mozTocH2" name="mozTocId937218"></a><a name="Sharing_C_Functions"></a>Sharing C Functions</h2><p>C
functions defined at the top level of a module can be made available
via cimport by putting headers for them in the .pxd file, for example,</p><table style="text-align: left; width: 100%;" border="0" cellpadding="5" cellspacing="2"><tbody><tr><td style="font-weight: bold; background-color: rgb(255, 204, 0);"><pre>volume.pxd</pre></td><td style="font-weight: bold; background-color: rgb(93, 186, 202);"><pre>spammery.pyx</pre></td></tr><tr><td style="vertical-align: top; background-color: rgb(255, 204, 0);"><pre>cdef float cube(float)</pre></td><td style="background-color: rgb(93, 186, 202);" colspan="1" rowspan="3"><pre>from volume cimport cube<br><br>def menu(description, size):<br>&nbsp; &nbsp; print description, ":", cube(size), \<br> "cubic metres of spam"<br><br>menu("Entree", 1)<br>menu("Main course", 3)<br>menu("Dessert", 2)</pre></td></tr><tr style="font-weight: bold;"><td style="vertical-align: top; background-color: rgb(153, 204, 51); height: 1px;"><pre>volume.pyx</pre></td></tr><tr><td style="vertical-align: top; background-color: rgb(153, 204, 51);"><pre>cdef float cube(float x):<br>&nbsp; &nbsp; return x * x * x</pre></td></tr></tbody></table><br><h2><a class="mozTocH2" name="mozTocId825278"></a><a name="Sharing_Extension_Types"></a>Sharing Extension Types</h2>
An extension type can be made available via cimport by splitting its definition into two parts, one in
a definition file and the other in the corresponding implementation file.
<br>
<br>
The definition part of the extension type can only declare C attributes
and C methods, not Python methods, and it must declare <i>all</i> of that
type's C attributes and C methods.<br>
<br>
The implementation part must implement all of the C methods declared in
the definition part, and may not add any further C attributes or methods. It may also
define Python methods.
<p>Here is an example of a module which defines and exports an extension
type, and another module which uses it. <br>
&nbsp;
<table cellpadding="5" cols="2" width="100%">
<tbody>
<tr>
<td bgcolor="#ffcc18" width="30%"><b><tt>Shrubbing.pxd</tt></b></td>
<td bgcolor="#5dbaca" width="50%"><b><tt>Shrubbing.pyx</tt></b></td>
</tr>
<tr align="left" valign="top">
<td bgcolor="#ffcc18" width="30%"><tt>cdef class Shrubbery:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; cdef int width</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; cdef int length</tt></td>
<td bgcolor="#5dbaca" width="50%"><tt>cdef class Shrubbery:</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; def __cinit__(self, int w, int l):</tt> <br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.width = w</tt>
<br>
<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.length = l</tt>
<p><tt>def standard_shrubbery():</tt> <br>
<tt>&nbsp;&nbsp;&nbsp; return Shrubbery(3, 7)</tt></p>
</td>
</tr>
<tr>
<td colspan="2" bgcolor="#8cbc1c" width="30%"><b><tt>Landscaping.pyx</tt></b></td>
</tr>
<tr>
<td colspan="2" bgcolor="#99cc00" width="30%"><tt>cimport Shrubbing</tt>
<br>
<tt>import Shrubbing</tt>
<p><tt>cdef Shrubbing.Shrubbery sh</tt> <br>
<tt>sh = Shrubbing.standard_shrubbery()</tt> <br>
<tt>print "Shrubbery size is %d x %d" % (sh.width, sh.length)</tt>
<br>
&nbsp;</p>
</td>
</tr>
</tbody>
</table>
</p>
<p>Some things to note about this example: </p>
<ul>
<li> There is a <tt>cdef</tt> <tt>class</tt> <tt>Shrubbery</tt> declaration in both Shrubbing.pxd
and Shrubbing.pyx. When the Shrubbing module is compiled, these two declarations
are combined into one.</li>
&nbsp; <li> In Landscaping.pyx, the <tt>cimport</tt> <tt>Shrubbing</tt> declaration
allows us to refer to the Shrubbery type as <tt>Shrubbing.Shrubbery</tt>.
But it doesn't bind the name <tt>Shrubbing</tt> in Landscaping's module namespace
at run time, so to access <tt>Shrubbing.standard_shrubbery</tt> we also
need to <tt>import</tt> <tt>Shrubbing</tt>.</li>
</ul>If you are exporting an extension type that has a base class, the
base class must be declared in the definition part. Repeating the base
class in the implementation part is not necessary, but if you do, it
must match the base class in the definition part.<h2><a class="mozTocH2" name="mozTocId144977"></a><a name="CircularCImports"></a>Circular cimports</h2>If
you have two structs, unions or extension types defined in different
.pxd files, and they need to refer to each other, there is a potential
for problems with circular imports. These problems can be avoided by
placing forward declarations of all the structs, unions and extension
types defined in the .pxd file <span style="font-style: italic;">before</span> the first <span style="font-family: monospace;">cimport</span> statement.<br><br>For example:<br><br><table style="text-align: left; margin-left: 40px;" border="1" cellpadding="5" cellspacing="2"><tbody><tr><td style="vertical-align: top; white-space: nowrap; text-align: left; background-color: rgb(255, 204, 24); font-family: monospace;">foo.pxd</td><td style="vertical-align: top; white-space: nowrap; text-align: left; background-color: rgb(255, 204, 24); font-family: monospace;">blarg.pxd</td></tr><tr><td style="vertical-align: top; white-space: nowrap; text-align: left; font-family: monospace; background-color: rgb(255, 204, 24);">cdef struct Spam<br><br>from blarg cimport Eggs<br><br>cdef struct Spam:<br>&nbsp;&nbsp;&nbsp;&nbsp;Eggs *eggs</td><td style="vertical-align: top; white-space: nowrap; text-align: left; background-color: rgb(255, 204, 24); font-family: monospace;">cdef struct Eggs<br><br>from foo cimport Spam<br><br>cdef struct Eggs:<br>&nbsp;&nbsp;&nbsp;&nbsp;Spam *spam</td></tr></tbody></table><br>If
the forward declarations weren't present, a circular import problem
would occur, analogous to that which arises in Python when two modules
try to import names from each
other. Placing the forward declarations before the <span style="font-family: monospace;">cimport</span> statements ensures that all type names are known to the Pyrex compiler sufficiently far in advance.<br><br>Note
that any .pyx file is free to cimport anything it wants from any .pxd
file without needing this precaution. It's only when two .pxd files
import each other that circular
import issues arise. <hr width="100%">Back to the <a href="overview.html">Language Overview</a>
<br>
<br>
</body></html>