You cannot 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
HTML
342 lines
15 KiB
HTML
<!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>
|
|
|
|
|
|
<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> sausage, eggs, lettuce</tt>
|
|
<p><tt>cdef struct spamdish:</tt> <br>
|
|
|
|
<tt> int oz_of_spam</tt> <br>
|
|
|
|
<tt> 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> d.oz_of_spam = 42</tt> <br>
|
|
|
|
<tt> d.filler = dishes.sausage</tt> </p>
|
|
|
|
|
|
<p><tt>def serve():</tt> <br>
|
|
|
|
<tt> cdef spamdish d</tt> <br>
|
|
|
|
<tt> prepare(&d)</tt> <br>
|
|
|
|
<tt> print "%d oz spam, filler no. %d" % \</tt>
|
|
<br>
|
|
|
|
<tt> (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>
|
|
|
|
|
|
<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> void eject_tomato(float)</tt></td>
|
|
|
|
<td bgcolor="#5dbaca"><tt>cimport c_lunch</tt>
|
|
<p><tt>def eject_tomato(float speed):</tt> <br>
|
|
|
|
<tt> 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> 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> 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>
|
|
|
|
|
|
<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> cdef int width</tt> <br>
|
|
|
|
<tt> cdef int length</tt></td>
|
|
|
|
<td bgcolor="#5dbaca" width="50%"><tt>cdef class Shrubbery:</tt> <br>
|
|
|
|
<tt> def __cinit__(self, int w, int l):</tt> <br>
|
|
|
|
<tt> self.width = w</tt>
|
|
<br>
|
|
|
|
<tt> self.length = l</tt>
|
|
|
|
<p><tt>def standard_shrubbery():</tt> <br>
|
|
|
|
<tt> 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>
|
|
|
|
</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>
|
|
|
|
|
|
<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> 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> 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> |