From: Gabriel Gellner Date: Fri, 2 May 2008 09:26:39 +0000 (-0700) Subject: Initial commit X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=a8312bd92e0e322aed48d8e5b41ef63172990eac;p=cython.git Initial commit --- a8312bd92e0e322aed48d8e5b41ef63172990eac diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..70a45cba --- /dev/null +++ b/Makefile @@ -0,0 +1,68 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html web htmlhelp latex changes linkcheck + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " web to make files usable by Sphinx.web" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview over all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf build/* + +html: + mkdir -p build/html build/doctrees + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html + @echo + @echo "Build finished. The HTML pages are in build/html." + +web: + mkdir -p build/web build/doctrees + $(SPHINXBUILD) -b web $(ALLSPHINXOPTS) build/web + @echo + @echo "Build finished; now you can run" + @echo " python -m sphinx.web build/web" + @echo "to start the server." + +htmlhelp: + mkdir -p build/htmlhelp build/doctrees + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in build/htmlhelp." + +latex: + mkdir -p build/latex build/doctrees + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex + @echo + @echo "Build finished; the LaTeX files are in build/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + mkdir -p build/changes build/doctrees + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes + @echo + @echo "The overview file is in build/changes." + +linkcheck: + mkdir -p build/linkcheck build/doctrees + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in build/linkcheck/output.txt." diff --git a/README b/README new file mode 100644 index 00000000..b67ec7b9 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +This is a collection of all the assorted pyrex/cython documentation assembled into +a unified Python style Sphinx project. It is hoped that this will become the default +documentation for the Cython tool set. diff --git a/conf.py b/conf.py new file mode 100644 index 00000000..064b066b --- /dev/null +++ b/conf.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +# +# Cython documentation build configuration file, created by +# sphinx-quickstart on Fri Apr 25 12:49:32 2008. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default value; values that are commented out +# serve to show the default value. + +import sys + +# If your extensions are in another directory, add it here. +#sys.path.append('some/directory') + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +#extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['.templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General substitutions. +project = 'Cython' +copyright = '2008, Stefan Behnel, Robert Bradshaw, William Stein, Gary Furnish, Dag Seljebotn, Gabriel Gellner, Greg Ewing' + +# The default replacements for |version| and |release|, also used in various +# other places throughout the built documents. +# +# The short X.Y version. +version = '0.9.6' +# The full version, including alpha/beta/rc tags. +release = '0.9.6.13.1' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['.static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Content template for the index page. +#html_index = '' + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If true, the reST sources are included in the HTML build as _sources/. +#html_copy_source = True + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Cythondoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +#_stdauthor = r'Greg Ewig\\ Gabriel Gellner, editor' +_stdauthor = r'Stefan Behnel, Robert Bradshaw, William Stein\\ Gary Furnish, Dag Seljebotn, Greg Ewing\\ Gabriel Gellner, editor' +latex_documents = [ + ('index', 'cython.tex', + 'Cython Manual', _stdauthor, 'manual') +] + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/docs/early_binding_for_speed.rst b/docs/early_binding_for_speed.rst new file mode 100644 index 00000000..c9db8c23 --- /dev/null +++ b/docs/early_binding_for_speed.rst @@ -0,0 +1,122 @@ +.. _early-binding-speed-label: + +Early Binding for Speed +======================= + +As a dynamic language, Python encourages a programming style of considering +classes and objects in terms of their methods and attributes, more than where +they fit into the class hierarchy. + +This can make Python a very relaxed and comfortable language for rapid +development, but with a price - the 'red tape' of managing data types is +dumped onto the interpreter. At run time, the interpreter does a lot of work +searching namespaces, fetching attributes and parsing argument and keyword +tuples. This run-time 'late binding' is a major cause of Python's relative +slowness compared to 'early binding' languages such as C++. + +However with Cython it is possible to gain significant speed-ups through the +use of 'early binding' programming techniques. + +For example, consider the following (silly) code example:: + + cdef class Rectangle: + cdef int x0, y0 + cdef int x1, y1 + def __init__(self, int x0, int y0, int x1, int y1): + self.x0 = x0; self.y0 = y0; self.x1 = x1; self.y1 = y1 + def area(self): + area = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + + def rectArea(x0, y0, x1, y1): + rect = Rectangle(x0, y0, x1, y1) + return rect.area() + +In the :func:`rectArea` method, the call to :meth:`rect.area` and the +:meth:`.area` method contain a lot of Python overhead. + +However, in Cython, it is possible to eliminate a lot of this overhead in cases +where calls occur within Cython code. For example:: + + cdef class Rectangle: + cdef int x0, y0 + cdef int x1, y1 + def __init__(self, int x0, int y0, int x1, int y1): + self.x0 = x0; self.y0 = y0; self.x1 = x1; self.y1 = y1 + cdef int _area(self): + int area + area = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + def area(self): + return self._area() + + def rectArea(x0, y0, x1, y1): + cdef Rectangle rect + rect = Rectangle(x0, y0, x1, y1) + return rect._area() + +Here, in the Rectangle extension class, we have defined two different area +calculation methods, the efficient :meth:`_area` C method, and the +Python-callable :meth:`area` method which serves as a thin wrapper around +:meth:`_area`. Note also in the function :func:`rectArea` how we 'early bind' +by declaring the local variable ``rect`` which is explicitly given the type +Rectangle. By using this declaration, instead of just dynamically assigning to +``rect``, we gain the ability to access the much more efficient C-callable +:meth:`_rect` method. + +But Cython offers us more simplicity again, by allowing us to declare +dual-access methods - methods that can be efficiently called at C level, but +can also be accessed from pure Python code at the cost of the Python access +overheads. Consider this code:: + + cdef class Rectangle: + cdef int x0, y0 + cdef int x1, y1 + def __init__(self, int x0, int y0, int x1, int y1): + self.x0 = x0; self.y0 = y0; self.x1 = x1; self.y1 = y1 + cpdef int area(self): + int area + area = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + + def rectArea(x0, y0, x1, y1): + cdef Rectangle rect + rect = Rectangle(x0, y0, x1, y1) + return rect.area() + +.. note:: + + in earlier versions of Cython, the :keyword:`cpdef` keyword is + :keyword:`rdef` - but has the same effect). + +Here, we just have a single area method, declared as :keyword:`cpdef` to make it +efficiently callable as a C function, but still accessible from pure Python +(or late-binding Cython) code. + +If within Cython code, we have a variable already 'early-bound' (ie, declared +explicitly as type Rectangle, (or cast to type Rectangle), then invoking its +area method will use the efficient C code path and skip the Python overhead. +But if in Pyrex or regular Python code we have a regular object variable +storing a Rectangle object, then invoking the area method will require: + +* an attribute lookup for the area method +* packing a tuple for arguments and a dict for keywords (both empty in this case) +* using the Python API to call the method + +and within the area method itself: + +* parsing the tuple and keywords +* executing the calculation code +* converting the result to a python object and returning it + +So within Cython, it is possible to achieve massive optimisations by +using strong typing in declaration and casting of variables. For tight loops +which use method calls, and where these methods are pure C, the difference can +be huge. + diff --git a/docs/extension_types.rst b/docs/extension_types.rst new file mode 100644 index 00000000..55afae4d --- /dev/null +++ b/docs/extension_types.rst @@ -0,0 +1,508 @@ + +Extension Types +=============== + +Introduction +------------ + +As well as creating normal user-defined classes with the Python class +statement, Cython also lets you create new built-in Python types, known as +extension types. You define an extension type using the :keyword:`cdef` class +statement. Here's an example:: + + cdef class Shrubbery: + + cdef int width, height + + def __init__(self, w, h): + self.width = w + self.height = h + + def describe(self): + print "This shrubbery is", self.width, \ + "by", self.height, "cubits." + +As you can see, a Cython extension type definition looks a lot like a Python +class definition. Within it, you use the def statement to define methods that +can be called from Python code. You can even define many of the special +methods such as :meth:`__init__` as you would in Python. + +The main difference is that you can use the :keyword:`cdef` statement to define +attributes. The attributes may be Python objects (either generic or of a +particular extension type), or they may be of any C data type. So you can use +extension types to wrap arbitrary C data structures and provide a Python-like +interface to them. + +Attributes +---------- + +Attributes of an extension type are stored directly in the object's C struct. +The set of attributes is fixed at compile time; you can't add attributes to an +extension type instance at run time simply by assigning to them, as you could +with a Python class instance. (You can subclass the extension type in Python +and add attributes to instances of the subclass, however.) + +There are two ways that attributes of an extension type can be accessed: by +Python attribute lookup, or by direct access to the C struct from Cython code. +Python code is only able to access attributes of an extension type by the +first method, but Cython code can use either method. + +By default, extension type attributes are only accessible by direct access, +not Python access, which means that they are not accessible from Python code. +To make them accessible from Python code, you need to declare them as +:keyword:`public` or :keyword:`readonly`. For example,:: + + cdef class Shrubbery: + cdef public int width, height + cdef readonly float depth + +makes the width and height attributes readable and writable from Python code, +and the depth attribute readable but not writable. + +.. note:: + + You can only expose simple C types, such as ints, floats and + strings, for Python access. You can also expose Python-valued attributes, + although read-write exposure is only possible for generic Python attributes + (of type object). If the attribute is declared to be of an extension type, it + must be exposed :keyword:`readonly`. + +.. note:: + + Also the :keyword:`public` and :keyword:`readonly` options apply only to + Python access, not direct access. All the attributes of an extension type + are always readable and writable by direct access. + +Type declarations +----------------- + +Before you can directly access the attributes of an extension type, the Cython +compiler must know that you have an instance of that type, and not just a +generic Python object. It knows this already in the case of the ``self`` +parameter of the methods of that type, but in other cases you will have to use +a type declaration. + +For example, in the following function,:: + + cdef widen_shrubbery(sh, extra_width): # BAD + sh.width = sh.width + extra_width + +because the ``sh`` parameter hasn't been given a type, the width attribute +will be accessed by a Python attribute lookup. If the attribute has been +declared :keyword:`public` or :keyword:`readonly` then this will work, but it +will be very inefficient. If the attribute is private, it will not work at all +-- the code will compile, but an attribute error will be raised at run time. + +The solution is to declare ``sh`` as being of type :class:`Shrubbery`, as +follows:: + + cdef widen_shrubbery(Shrubbery sh, extra_width): + sh.width = sh.width + extra_width + +Now the Cython compiler knows that ``sh`` has a C attribute called +:attr:`width` and will generate code to access it directly and efficiently. +The same consideration applies to local variables, for example,:: + + cdef Shrubbery another_shrubbery(Shrubbery sh1): + cdef Shrubbery sh2 + sh2 = Shrubbery() + sh2.width = sh1.width + sh2.height = sh1.height + return sh2 + +Extension types and None +------------------------ + +When you declare a parameter or C variable as being of an extension type, +Cython will allow it to take on the value ``None`` as well as values of its +declared type. This is analogous to the way a C pointer can take on the value +``NULL``, and you need to exercise the same caution because of it. There is no +problem as long as you are performing Python operations on it, because full +dynamic type checking will be applied. However, when you access C attributes +of an extension type (as in the widen_shrubbery function above), it's up to +you to make sure the reference you're using is not ``None`` -- in the +interests of efficiency, Cython does not check this. + +You need to be particularly careful when exposing Python functions which take +extension types as arguments. If we wanted to make :func:`widen_shrubbery` a +Python function, for example, if we simply wrote:: + + def widen_shrubbery(Shrubbery sh, extra_width): # This is + sh.width = sh.width + extra_width # dangerous! + +then users of our module could crash it by passing ``None`` for the ``sh`` +parameter. + +One way to fix this would be:: + + def widen_shrubbery(Shrubbery sh, extra_width): + if sh is None: + raise TypeError + sh.width = sh.width + extra_width + +but since this is anticipated to be such a frequent requirement, Cython +provides a more convenient way. Parameters of a Python function declared as an +extension type can have a ``not None`` clause:: + + def widen_shrubbery(Shrubbery sh not None, extra_width): + sh.width = sh.width + extra_width + +Now the function will automatically check that ``sh`` is ``not None`` along +with checking that it has the right type. + +.. note:: + + ``not None`` clause can only be used in Python functions (defined with + :keyword:`def`) and not C functions (defined with :keyword:`cdef`). If + you need to check whether a parameter to a C function is None, you will + need to do it yourself. + +.. note:: + + Some more things: + + * The self parameter of a method of an extension type is guaranteed never to + be ``None``. + * When comparing a value with ``None``, keep in mind that, if ``x`` is a Python + object, ``x is None`` and ``x is not None`` are very efficient because they + translate directly to C pointer comparisons, whereas ``x == None`` and + ``x != None``, or simply using ``x`` as a boolean value (as in ``if x: ...``) + will invoke Python operations and therefore be much slower. + +Special methods +--------------- + +Although the principles are similar, there are substantial differences between +many of the :meth:`__xxx__` special methods of extension types and their Python +counterparts. There is a separate page devoted to this subject, and you should +read it carefully before attempting to use any special methods in your +extension types. + +Properties +---------- + +There is a special syntax for defining properties in an extension class:: + + cdef class Spam: + + property cheese: + + "A doc string can go here." + + def __get__(self): + # This is called when the property is read. + ... + + def __set__(self, value): + # This is called when the property is written. + ... + + def __del__(self): + # This is called when the property is deleted. + + +The :meth:`__get__`, :meth:`__set__` and :meth:`__del__` methods are all +optional; if they are omitted, an exception will be raised when the +corresponding operation is attempted. + +Here's a complete example. It defines a property which adds to a list each +time it is written to, returns the list when it is read, and empties the list +when it is deleted.:: + + #cheesy.pyx Test input + cdef class CheeseShop: + + cdef object cheeses + + def __cinit__(self): + self.cheeses = [] + + property cheese: + + def __get__(self): + return "We don't have: %s" % self.cheeses + + def __set__(self, value): + self.cheeses.append(value) + + def __del__(self): + del self.cheeses[:] + + from cheesy import CheeseShop + + shop = CheeseShop() + print shop.cheese + + shop.cheese = "camembert" + print shop.cheese + + shop.cheese = "cheddar" + print shop.cheese + + del shop.cheese + print shop.cheese + + #Test output + We don't have: [] + We don't have: ['camembert'] + We don't have: ['camembert', 'cheddar'] + We don't have: [] + +Subclassing +----------- + +An extension type may inherit from a built-in type or another extension type:: + + cdef class Parrot: + ... + + cdef class Norwegian(Parrot): + ... + + +A complete definition of the base type must be available to Cython, so if the +base type is a built-in type, it must have been previously declared as an +extern extension type. If the base type is defined in another Cython module, it +must either be declared as an extern extension type or imported using the +:keyword:`cimport` statement. + +An extension type can only have one base class (no multiple inheritance). + +Cython extension types can also be subclassed in Python. A Python class can +inherit from multiple extension types provided that the usual Python rules for +multiple inheritance are followed (i.e. the C layouts of all the base classes +must be compatible). + +C methods +========= +Extension types can have C methods as well as Python methods. Like C +functions, C methods are declared using :keyword:`cdef` instead of +:keyword:`def`. C methods are "virtual", and may be overridden in derived +extension types.:: + + pets.pyx + Output + cdef class Parrot: + + cdef void describe(self): + print "This parrot is resting." + + cdef class Norwegian(Parrot): + + cdef void describe(self): + Parrot.describe(self) + print "Lovely plumage!" + + + cdef Parrot p1, p2 + p1 = Parrot() + p2 = Norwegian() + print "p1:" + p1.describe() + print "p2:" + p2.describe() + p1: + This parrot is resting. + p2: + This parrot is resting. + Lovely plumage! + +The above example also illustrates that a C method can call an inherited C +method using the usual Python technique, i.e.:: + + Parrot.describe(self) + +Forward-declaring extension types +--------------------------------- + +Extension types can be forward-declared, like :keyword:`struct` and +:keyword:`union` types. This will be necessary if you have two extension types +that need to refer to each other, e.g.:: + + cdef class Shrubbery # forward declaration + + cdef class Shrubber: + cdef Shrubbery work_in_progress + + cdef class Shrubbery: + cdef Shrubber creator + +If you are forward-declaring an extension type that has a base class, you must +specify the base class in both the forward declaration and its subsequent +definition, for example,:: + + cdef class A(B) + + ... + + cdef class A(B): + # attributes and methods + +Making extension types weak-referenceable +----------------------------------------- + +By default, extension types do not support having weak references made to +them. You can enable weak referencing by declaring a C attribute of type +object called :attr:`__weakref__`. For example,:: + + cdef class ExplodingAnimal: + """This animal will self-destruct when it is + no longer strongly referenced.""" + + cdef object __weakref__ + +Public and external extension types +----------------------------------- + +Extension types can be declared extern or public. An extern extension type +declaration makes an extension type defined in external C code available to a +Cython module. A public extension type declaration makes an extension type +defined in a Cython module available to external C code. + +External extension types +^^^^^^^^^^^^^^^^^^^^^^^^ + +An extern extension type allows you to gain access to the internals of Python +objects defined in the Python core or in a non-Cython extension module. + +.. note:: + + In Pyrex versions before 0.8, extern extension types were also used to + reference extension types defined in another Pyrex module. While you can still + do that, Cython provides a better mechanism for this. See + :ref:`sharing-declarations-label`. + +Here is an example which will let you get at the C-level members of the +built-in complex object.:: + + cdef extern from "complexobject.h": + + struct Py_complex: + double real + double imag + + ctypedef class __builtin__.complex [object PyComplexObject]: + cdef Py_complex cval + + # A function which uses the above type + def spam(complex c): + print "Real:", c.cval.real + print "Imag:", c.cval.imag + +.. note:: + + Some important things: + + 1. In this example, :keyword:`ctypedef` class has been used. This is + because, in the Python header files, the ``PyComplexObject`` struct is + declared with:: + + ctypedef struct { + ... + } PyComplexObject; + + 2. As well as the name of the extension type, the module in which its type + object can be found is also specified. See the implicit importing section + below. + + 3. When declaring an external extension type, you don't declare any + methods. Declaration of methods is not required in order to call them, + because the calls are Python method calls. Also, as with + :keyword:`structs` and :keyword:`unions`, if your extension class + declaration is inside a :keyword:`cdef` extern from block, you only need to + declare those C members which you wish to access. + +Implicit importing +^^^^^^^^^^^^^^^^^^ + +Cython requires you to include a module name in an extern extension class +declaration, for example,:: + + cdef extern class MyModule.Spam: + ... + +The type object will be implicitly imported from the specified module and +bound to the corresponding name in this module. In other words, in this +example an implicit:: + + from MyModule import Spam + +statement will be executed at module load time. + +The module name can be a dotted name to refer to a module inside a package +hierarchy, for example,:: + + cdef extern class My.Nested.Package.Spam: + ... + +You can also specify an alternative name under which to import the type using +an as clause, for example,:: + + cdef extern class My.Nested.Package.Spam as Yummy: + ... + +which corresponds to the implicit import statement:: + + from My.Nested.Package import Spam as Yummy + +Type names vs. constructor names +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Inside a Cython module, the name of an extension type serves two distinct +purposes. When used in an expression, it refers to a module-level global +variable holding the type's constructor (i.e. its type-object). However, it +can also be used as a C type name to declare variables, arguments and return +values of that type. + +When you declare:: + + cdef extern class MyModule.Spam: + ... + +the name Spam serves both these roles. There may be other names by which you +can refer to the constructor, but only Spam can be used as a type name. For +example, if you were to explicity import MyModule, you could use +``MyModule.Spam()`` to create a Spam instance, but you wouldn't be able to use +:class:`MyModule.Spam` as a type name. + +When an as clause is used, the name specified in the as clause also takes over +both roles. So if you declare:: + + cdef extern class MyModule.Spam as Yummy: + ... + +then Yummy becomes both the type name and a name for the constructor. Again, +there are other ways that you could get hold of the constructor, but only +Yummy is usable as a type name. + +Public extension types +^^^^^^^^^^^^^^^^^^^^^^ + +An extension type can be declared public, in which case a ``.h`` file is +generated containing declarations for its object struct and type object. By +including the ``.h`` file in external C code that you write, that code can +access the attributes of the extension type. + +Name specification clause +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The part of the class declaration in square brackets is a special feature only +available for extern or public extension types. The full form of this clause +is:: + + [object object_struct_name, type type_object_name ] + +where ``object_struct_name`` is the name to assume for the type's C struct, +and type_object_name is the name to assume for the type's statically declared +type object. (The object and type clauses can be written in either order.) + +If the extension type declaration is inside a :keyword:`cdef` extern from +block, the object clause is required, because Cython must be able to generate +code that is compatible with the declarations in the header file. Otherwise, +for extern extension types, the object clause is optional. + +For public extension types, the object and type clauses are both required, +because Cython must be able to generate code that is compatible with external C +code. + + diff --git a/docs/external_C_code.rst b/docs/external_C_code.rst new file mode 100644 index 00000000..3e1a5c59 --- /dev/null +++ b/docs/external_C_code.rst @@ -0,0 +1,415 @@ +Interfacing with External C Code +================================ + +One of the main uses of Cython is wrapping existing libraries of C code. This +is achieved by using external declarations to declare the C functions and +variables from the library that you want to use. + +You can also use public declarations to make C functions and variables defined +in a Cython module available to external C code. The need for this is expected +to be less frequent, but you might want to do it, for example, if you are +embedding Python in another application as a scripting language. Just as a +Cython module can be used as a bridge to allow Python code to call C code, it +can also be used to allow C code to call Python code. + +External declarations +--------------------- + +By default, C functions and variables declared at the module level are local +to the module (i.e. they have the C static storage class). They can also be +declared extern to specify that they are defined elsewhere, for example:: + + cdef extern int spam_counter + + cdef extern void order_spam(int tons) + +Referencing C header files +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When you use an extern definition on its own as in the examples above, Cython +includes a declaration for it in the generated C file. This can cause problems +if the declaration doesn't exactly match the declaration that will be seen by +other C code. If you're wrapping an existing C library, for example, it's +important that the generated C code is compiled with exactly the same +declarations as the rest of the library. + +To achieve this, you can tell Cython that the declarations are to be found in a +C header file, like this:: + + cdef extern from "spam.h": + + int spam_counter + + void order_spam(int tons) + +The ``cdef extern`` from clause does three things: + +1. It directs Cython to place a ``#include`` statement for the named header file in + the generated C code. +2. It prevents Cython from generating any C code + for the declarations found in the associated block. +3. It treats all declarations within the block as though they started with + ``cdef extern``. + +It's important to understand that Cython does not itself read the C header +file, so you still need to provide Cython versions of any declarations from it +that you use. However, the Cython declarations don't always have to exactly +match the C ones, and in some cases they shouldn't or can't. In particular: + +1. Don't use ``const``. Cython doesn't know anything about ``const``, so just + leave it out. Most of the time this shouldn't cause any problem, although + on rare occasions you might have to use a cast. + + .. warning:: + + A problem with const could arise if you have something like:: + + cdef extern from "grail.h": + char *nun + + where grail.h actually contains:: + + extern const char *nun; + + and you do:: + + cdef void languissement(char *s): + #something that doesn't change s + + ... + + languissement(nun) + + which will cause the C compiler to complain. You can work around it by + casting away the constness:: + + languissement(nun) + +2. Leave out any platform-specific extensions to C declarations such as + ``__declspec()``. + +3. If the header file declares a big struct and you only want to use a few + members, you only need to declare the members you're interested in. Leaving + the rest out doesn't do any harm, because the C compiler will use the full + definition from the header file. + + In some cases, you might not need any of the struct's members, in which + case you can just put pass in the body of the struct declaration, e.g.:: + + cdef extern from "foo.h": + struct spam: + pass + + .. note:: + + you can only do this inside a ``cdef extern from`` block; struct + declarations anywhere else must be non-empty. + + + +4. If the header file uses ``typedef`` names such as :ctype:`size_t` to refer + to platform-dependent flavours of numeric types, you will need a + corresponding :keyword:`ctypedef` statement, but you don't need to match + the type exactly, just use something of the right general kind (int, float, + etc). For example,:: + + ctypedef int size_t + + will work okay whatever the actual size of a :ctype:`size_t` is (provided the header + file defines it correctly). + +5. If the header file uses macros to define constants, translate them into a + dummy ``enum`` declaration. + +6. If the header file defines a function using a macro, declare it as though + it were an ordinary function, with appropriate argument and result types. + +A few more tricks and tips: + +* If you want to include a C header because it's needed by another header, but + don't want to use any declarations from it, put pass in the extern-from + block:: + + cdef extern from "spam.h": + pass + +* If you want to include some external declarations, but don't want to specify + a header file (because it's included by some other header that you've + already included) you can put ``*`` in place of the header file name:: + + cdef extern from *: + ... + +Styles of struct, union and enum declaration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are two main ways that structs, unions and enums can be declared in C +header files: using a tag name, or using a typedef. There are also some +variations based on various combinations of these. + +It's important to make the Cython declarations match the style used in the +header file, so that Cython can emit the right sort of references to the type +in the code it generates. To make this possible, Cython provides two different +syntaxes for declaring a struct, union or enum type. The style introduced +above corresponds to the use of a tag name. To get the other style, you prefix +the declaration with :keyword:`ctypedef`, as illustrated below. + +The following table shows the various possible styles that can be found in a +header file, and the corresponding Cython declaration that you should put in +the ``cdef extern`` from block. Struct declarations are used as an example; the +same applies equally to union and enum declarations. + +Note that in all the cases below, you refer to the type in Cython code simply +as :ctype:`Foo`, not ``struct Foo``. + +Accessing Python/C API routines +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One particular use of the ``cdef extern from`` statement is for gaining access to +routines in the Python/C API. For example,:: + + cdef extern from "Python.h": + + object PyString_FromStringAndSize(char *s, Py_ssize_t len) + +will allow you to create Python strings containing null bytes. + +Special Types +^^^^^^^^^^^^^ + +Cython predefines the name ``Py_ssize_t`` for use with Python/C API routines. To +make your extensions compatible with 64-bit systems, you should always use +this type where it is specified in the documentation of Python/C API routines. + +Windows Calling Conventions +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``__stdcall`` and ``__cdecl`` calling convention specifiers can be used in +Cython, with the same syntax as used by C compilers on Windows, for example,:: + + cdef extern int __stdcall FrobnicateWindow(long handle) + + cdef void (__stdcall *callback)(void *) + +If ``__stdcall`` is used, the function is only considered compatible with +other ``__stdcall`` functions of the same signature. + +Resolving naming conflicts - C name specifications +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Each Cython module has a single module-level namespace for both Python and C +names. This can be inconvenient if you want to wrap some external C functions +and provide the Python user with Python functions of the same names. + +Cython provides a couple of different ways of solving this problem. The +best way, especially if you have many C functions to wrap, is probably to put +the extern C function declarations into a different namespace using the +facilities described in the section on sharing declarations between Cython +modules. + +The other way is to use a C name specification to give different Cython and C +names to the C function. Suppose, for example, that you want to wrap an +external function called :func:`eject_tomato`. If you declare it as:: + + cdef extern void c_eject_tomato "eject_tomato" (float speed) + +then its name inside the Cython module will be ``c_eject_tomato``, whereas its name +in C will be ``eject_tomato``. You can then wrap it with:: + + def eject_tomato(speed): + c_eject_tomato(speed) + +so that users of your module can refer to it as ``eject_tomato``. + +Another use for this feature is referring to external names that happen to be +Cython keywords. For example, if you want to call an external function called +print, you can rename it to something else in your Cython module. + +As well as functions, C names can be specified for variables, structs, unions, +enums, struct and union members, and enum values. For example,:: + + cdef extern int one "ein", two "zwei" + cdef extern float three "drei" + + cdef struct spam "SPAM": + int i "eye" + + cdef enum surprise "inquisition": + first "alpha" + second "beta" = 3 + +Using Cython Declarations from C +-------------------------------- + +Cython provides two methods for making C declarations from a Cython module +available for use by external C code – public declarations and C API +declarations. + +.. note:: + + You do not need to use either of these to make declarations from one + Cython module available to another Cython module – you should use the + :keyword:`cimport` statement for that. Sharing Declarations Between Cython Modules. + +Public Declarations +^^^^^^^^^^^^^^^^^^^ + +You can make C types, variables and functions defined in a Cython module +accessible to C code that is linked with the module, by declaring them with +the public keyword:: + + cdef public struct Bunny: # public type declaration + int vorpalness + + cdef public int spam # public variable declaration + + cdef public void grail(Bunny *): # public function declaration + ... + +If there are any public declarations in a Cython module, a header file called +:file:`modulename.h` file is generated containing equivalent C declarations for +inclusion in other C code. + +Any C code wanting to make use of these declarations will need to be linked, +either statically or dynamically, with the extension module. + +If the Cython module resides within a package, then the name of the ``.h`` +file consists of the full dotted name of the module, e.g. a module called +:mod:`foo.spam` would have a header file called :file:`foo.spam.h`. + +C API Declarations +^^^^^^^^^^^^^^^^^^ + +The other way of making declarations available to C code is to declare them +with the :keyword:`api` keyword. You can use this keyword with C functions and +extension types. A header file called :file:`modulename_api.h` is produced +containing declarations of the functions and extension types, and a function +called :func:`import_modulename`. + +C code wanting to use these functions or extension types needs to include the +header and call the :func:`import_modulename` function. The other functions +can then be called and the extension types used as usual. + +Any public C type or extension type declarations in the Cython module are also +made available when you include :file:`modulename_api.h`.:: + + delorean.pyx + + marty.c + + cdef public struct Vehicle: + int speed + float power + + cdef api void activate(Vehicle *v): + if v.speed >= 88 and v.power >= 1.21: + print "Time travel achieved" + + #include "delorean_api.h" + + Vehicle car; + + int main(int argc, char *argv[]) { + import_delorean(); + car.speed = atoi(argv[1]); + car.power = atof(argv[2]); + activate(&car); + } + +.. note:: + + Any types defined in the Cython module that are used as argument or + return types of the exported functions will need to be declared public, + otherwise they won't be included in the generated header file, and you will + get errors when you try to compile a C file that uses the header. + +Using the :keyword:`api` method does not require the C code using the +declarations to be linked with the extension module in any way, as the Python +import machinery is used to make the connection dynamically. However, only +functions can be accessed this way, not variables. + +You can use both :keyword:`public` and :keyword:`api` on the same function to +make it available by both methods, e.g.:: + + cdef public api void belt_and_braces(): + ... + +However, note that you should include either :file:`modulename.h` or +:file:`modulename_api.h` in a given C file, not both, otherwise you may get +conflicting dual definitions. + +If the Cython module resides within a package, then: + +* The name of the header file contains of the full dotted name of the module. +* The name of the importing function contains the full name with dots replaced + by double underscores. + +E.g. a module called :mod:`foo.spam` would have an API header file called +:file:`foo.spam_api.h` and an importing function called +:func:`import_foo__spam`. + +Multiple public and api declarations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can declare a whole group of items as :keyword:`public` and/or +:keyword:`api` all at once by enclosing them in a :keyword:`cdef` block, for +example,:: + + cdef public api: + void order_spam(int tons) + char *get_lunch(float tomato_size) + +This can be a useful thing to do in a ``.pxd`` file (see +:ref:`sharing-declarations-label`) to make the module's public interface +available by all three methods. + +Acquiring and Releasing the GIL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Cython provides facilities for releasing the Global Interpreter Lock (GIL) +before calling C code, and for acquiring the GIL in functions that are to be +called back from C code that is executed without the GIL. + +Releasing the GIL +^^^^^^^^^^^^^^^^^ + +You can release the GIL around a section of code using the +:keyword:`with nogil` statement:: + + with nogil: + + +Code in the body of the statement must not manipulate Python objects in any +way, and must not call anything that manipulates Python objects without first +re-acquiring the GIL. Cython currently does not check this. + +Acquiring the GIL +^^^^^^^^^^^^^^^^^ + +A C function that is to be used as a callback from C code that is executed +without the GIL needs to acquire the GIL before it can manipulate Python +objects. This can be done by specifying with :keyword:`gil` in the function +header:: + + cdef void my_callback(void *data) with gil: + ... + +Declaring a function as callable without the GIL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can specify :keyword:`nogil` in a C function header or function type to +declare that it is safe to call without the GIL.:: + + cdef void my_gil_free_func(int spam) nogil: + ... + +If you are implementing such a function in Cython, it cannot have any Python +arguments, Python local variables, or Python return type, and cannot +manipulate Python objects in any way or call any function that does so without +acquiring the GIL first. Some of these restrictions are currently checked by +Cython, but not all. It is possible that more stringent checking will be +performed in the future. + +Declaring a function with :keyword:`gil` also implicitly makes its signature +:keyword:`nogil`. + diff --git a/docs/language_basics.rst b/docs/language_basics.rst new file mode 100644 index 00000000..249b0a4b --- /dev/null +++ b/docs/language_basics.rst @@ -0,0 +1,571 @@ +.. _language-basics-label: + +Language Basics +=============== + +Python functions vs. C functions +-------------------------------- + +There are two kinds of function definition in Cython: + +Python functions are defined using the def statement, as in Python. They take +Python objects as parameters and return Python objects. + +C functions are defined using the new :keyword:`cdef` statement. They take +either Python objects or C values as parameters, and can return either Python +objects or C values. + +Within a Cython module, Python functions and C functions can call each other +freely, but only Python functions can be called from outside the module by +interpreted Python code. So, any functions that you want to "export" from your +Cython module must be declared as Python functions using def. + +Parameters of either type of function can be declared to have C data types, +using normal C declaration syntax. For example,:: + + def spam(int i, char *s): + ... + + cdef int eggs(unsigned long l, float f): + ... + +When a parameter of a Python function is declared to have a C data type, it is +passed in as a Python object and automatically converted to a C value, if +possible. Automatic conversion is currently only possible for numeric types +and string types; attempting to use any other type for the parameter of a +Python function will result in a compile-time error. + +C functions, on the other hand, can have parameters of any type, since they're +passed in directly using a normal C function call. + +Python objects as parameters and return values +---------------------------------------------- + +If no type is specified for a parameter or return value, it is assumed to be a +Python object. (Note that this is different from the C convention, where it +would default to int.) For example, the following defines a C function that +takes two Python objects as parameters and returns a Python object:: + + cdef spamobjs(x, y): + ... + +Reference counting for these objects is performed automatically according to +the standard Python/C API rules (i.e. borrowed references are taken as +parameters and a new reference is returned). + +The name object can also be used to explicitly declare something as a Python +object. This can be useful if the name being declared would otherwise be taken +as the name of a type, for example,:: + + cdef ftang(object int): + ... + +declares a parameter called int which is a Python object. You can also use +object as the explicit return type of a function, e.g.:: + + cdef object ftang(object int): + ... + +In the interests of clarity, it is probably a good idea to always be explicit +about object parameters in C functions. + +C variable and type definitions +------------------------------- + +The :keyword:`cdef` statement is also used to declare C variables, either local or +module-level:: + + cdef int i, j, k + cdef float f, g[42], *h + +and C :keyword:`struct`, :keyword:`union` or :keyword:`enum` types:: + + cdef struct Grail: + int age + float volume + + cdef union Food: + char *spam + float *eggs + + cdef enum CheeseType: + cheddar, edam, + camembert + + cdef enum CheeseState: + hard = 1 + soft = 2 + runny = 3 + +There is currently no special syntax for defining a constant, but you can use +an anonymous :keyword:`enum` declaration for this purpose, for example,:: + + cdef enum: + tons_of_spam = 3 + +.. note:: + the words ``struct``, ``union`` and ``enum`` are used only when + defining a type, not when referring to it. For example, to declare a variable + pointing to a ``Grail`` you would write:: + + cdef Grail *gp + + and not:: + + cdef struct Grail *gp # WRONG + + There is also a ``ctypedef`` statement for giving names to types, e.g.:: + + ctypedef unsigned long ULong + + ctypedef int *IntPtr + +Grouping multiple C declarations +================================ + +If you have a series of declarations that all begin with :keyword:`cdef`, you +can group them into a :keyword:`cdef` block like this:: + + cdef: + struct Spam: + int tons + + int i + float f + Spam *p + + void f(Spam *s): + print s.tons, "Tons of spam" + +Automatic type conversions +-------------------------- + +In most situations, automatic conversions will be performed for the basic +numeric and string types when a Python object is used in a context requiring a +C value, or vice versa. The following table summarises the conversion +possibilities. + ++----------------------------+--------------------+------------------+ +| C types | From Python types | To Python types | ++============================+====================+==================+ +| [unsigned] char | int, long | int | +| [unsigned] short | | | +| int, long | | | ++----------------------------+--------------------+------------------+ +| unsigned int | int, long | long | +| unsigned long | | | +| [unsigned] long long | | | ++----------------------------+--------------------+------------------+ +| float, double, long double | int, long, float | float | ++----------------------------+--------------------+------------------+ +| char * | str | str | ++----------------------------+--------------------+------------------+ + +Caveats when using a Python string in a C context +------------------------------------------------- + +You need to be careful when using a Python string in a context expecting a +``char *``. In this situation, a pointer to the contents of the Python string is +used, which is only valid as long as the Python string exists. So you need to +make sure that a reference to the original Python string is held for as long +as the C string is needed. If you can't guarantee that the Python string will +live long enough, you will need to copy the C string. + +Cython detects and prevents some mistakes of this kind. For instance, if you +attempt something like:: + + cdef char *s + s = pystring1 + pystring2 + +then Cython will produce the error message ``Obtaining char * from temporary +Python value``. The reason is that concatenating the two Python strings +produces a new Python string object that is referenced only by a temporary +internal variable that Cython generates. As soon as the statement has finished, +the temporary variable will be decrefed and the Python string deallocated, +leaving ``s`` dangling. Since this code could not possibly work, Cython refuses to +compile it. + +The solution is to assign the result of the concatenation to a Python +variable, and then obtain the ``char *`` from that, i.e.:: + + cdef char *s + p = pystring1 + pystring2 + s = p + +It is then your responsibility to hold the reference p for as long as +necessary. + +Keep in mind that the rules used to detect such errors are only heuristics. +Sometimes Cython will complain unnecessarily, and sometimes it will fail to +detect a problem that exists. Ultimately, you need to understand the issue and +be careful what you do. + +Scope rules +----------- + +Cython determines whether a variable belongs to a local scope, the module +scope, or the built-in scope completely statically. As with Python, assigning +to a variable which is not otherwise declared implicitly declares it to be a +Python variable residing in the scope where it is assigned. Unlike Python, +however, a name which is referred to but not declared or assigned is assumed +to reside in the builtin scope, not the module scope. Names added to the +module dictionary at run time will not shadow such names. + +You can use a global statement at the module level to explicitly declare a +name to be a module-level name when there would otherwise not be any +indication of this, for example,:: + + global __name__ + print __name__ + +Without the global statement, the above would print the name of the builtins +module. + +.. note:: + A consequence of these rules is that the module-level scope behaves the + same way as a Python local scope if you refer to a variable before assigning + to it. In particular, tricks such as the following will not work in Cython:: + + try: + x = True + except NameError: + True = 1 + + because, due to the assignment, the True will always be looked up in the + module-level scope. You would have to do something like this instead:: + + import __builtin__ + try: + True = __builtin__.True + except AttributeError: + True = 1 + +Statements and expressions +-------------------------- + +Control structures and expressions follow Python syntax for the most part. +When applied to Python objects, they have the same semantics as in Python +(unless otherwise noted). Most of the Python operators can also be applied to +C values, with the obvious semantics. + +If Python objects and C values are mixed in an expression, conversions are +performed automatically between Python objects and C numeric or string types. + +Reference counts are maintained automatically for all Python objects, and all +Python operations are automatically checked for errors, with appropriate +action taken. + +Differences between C and Cython expressions +-------------------------------------------- + +There are some differences in syntax and semantics between C expressions and +Cython expressions, particularly in the area of C constructs which have no +direct equivalent in Python. + +* An integer literal without an L suffix is treated as a C constant, and will + be truncated to whatever size your C compiler thinks appropriate. With an + L suffix, it will be converted to Python long integer (even if it would + be small enough to fit into a C int). +* There is no ``->`` operator in Cython. Instead of ``p->x``, use ``p.x`` +* There is no ``*`` operator in Cython. Instead of ``*p``, use ``p[0]`` +* There is an ``&`` operator, with the same semantics as in C. +* The null C pointer is called ``NULL``, not ``0`` (and ``NULL`` is a reserved word). +* Character literals are written with a c prefix, for example:: + + c'X' + +* Type casts are written ``value`` , for example:: + + cdef char *p, float *q + p = q + + Warning: Don't attempt to use a typecast to convert between Python and C + data types -- it won't do the right thing. Leave Cython to perform the + conversion automatically. + +Operator Precedence +------------------- + +Keep in mind that there are some differences in operator precedence between +Python and C, and that Cython uses the Python precedences, not the C ones. + +Integer for-loops +----------------- + +You should be aware that a for-loop such as:: + + for i in range(n): + ... + +won't be very fast, even if i and n are declared as C integers, because range +is a Python function. For iterating over ranges of integers, Cython has another +form of for-loop:: + + for i from 0 <= i < n: + ... + +If the loop variable and the lower and upper bounds are all C integers, this +form of loop will be much faster, because Cython will translate it into pure C +code. + +Some things to note about the for-from loop: + +* The target expression must be a variable name. +* The name between the lower and upper bounds must be the same as the target + name. +* The direction of iteration is determined by the relations. If they are both + from the set {``<``, ``<=``} then it is upwards; if they are both from the set + {``>``, ``>=``} then it is downwards. (Any other combination is disallowed.) + +Like other Python looping statements, break and continue may be used in the +body, and the loop may have an else clause. + +.. note:: + + See :ref:`automatic-range-conversion` + +Error return values +------------------- + +If you don't do anything special, a function declared with :keyword`cdef` that +does not return a Python object has no way of reporting Python exceptions to +its caller. If an exception is detected in such a function, a warning message +is printed and the exception is ignored. + +If you want a C function that does not return a Python object to be able to +propagate exceptions to its caller, you need to declare an exception value for +it. Here is an example:: + + cdef int spam() except -1: + ... + +With this declaration, whenever an exception occurs inside spam, it will +immediately return with the value ``-1``. Furthermore, whenever a call to spam +returns ``-1``, an exception will be assumed to have occurred and will be +propagated. + +When you declare an exception value for a function, you should never +explicitly return that value. If all possible return values are legal and you +can't reserve one entirely for signalling errors, you can use an alternative +form of exception value declaration:: + + cdef int spam() except? -1: + ... + +The "?" indicates that the value ``-1`` only indicates a possible error. In this +case, Cython generates a call to :cfunc:`PyErr_Occurred` if the exception value is +returned, to make sure it really is an error. + +There is also a third form of exception value declaration:: + + cdef int spam() except *: + ... + +This form causes Cython to generate a call to :cfunc:`PyErr_Occurred` after +every call to spam, regardless of what value it returns. If you have a +function returning void that needs to propagate errors, you will have to use +this form, since there isn't any return value to test. + +Some things to note: + +* Exception values can only declared for functions returning an integer, enum, + float or pointer type, and the value must be a constant expression. The + only possible pointer exception value is ``NULL``. Void functions can only + use the ``except *`` form. +* The exception value specification is part of the signature of the function. + If you're passing a pointer to a function as a parameter or assigning it + to a variable, the declared type of the parameter or variable must have + the same exception value specification (or lack thereof). Here is an + example of a pointer-to-function declaration with an exception + value:: + + int (*grail)(int, char *) except -1 + +* You don't need to (and shouldn't) declare exception values for functions + which return Python objects. Remember that a function with no declared + return type implicitly returns a Python object. + +Checking return values of non-Cython functions +---------------------------------------------- + +It's important to understand that the except clause does not cause an error to +be raised when the specified value is returned. For example, you can't write +something like:: + + cdef extern FILE *fopen(char *filename, char *mode) except NULL # WRONG! + +and expect an exception to be automatically raised if a call to :func:`fopen` +returns ``NULL``. The except clause doesn't work that way; its only purpose is +for propagating exceptions that have already been raised, either by a Cython +function or a C function that calls Python/C API routines. To get an exception +from a non-Python-aware function such as :func:`fopen`, you will have to check the +return value and raise it yourself, for example,:: + + cdef FILE *p + p = fopen("spam.txt", "r") + if p == NULL: + raise SpamError("Couldn't open the spam file") + +The include statement +--------------------- + +A Cython source file can include material from other files using the include +statement, for example:: + + include "spamstuff.pxi" + +The contents of the named file are textually included at that point. The +included file can contain any complete statements or declarations that are +valid in the context where the include statement appears, including other +include statements. The contents of the included file should begin at an +indentation level of zero, and will be treated as though they were indented to +the level of the include statement that is including the file. + +.. note:: + + There are other mechanisms available for splitting Cython code into + separate parts that may be more appropriate in many cases. See + :ref:`sharing-declarations-label`. + +Keyword-only arguments +---------------------- + +Python functions can have keyword-only arguments listed after the ``*`` +parameter and before the ``**`` parameter if any, e.g.:: + + def f(a, b, *args, c, d = 42, e, **kwds): + ... + +Here ``c``, ``d`` and ``e`` cannot be passed as position arguments and must be +passed as keyword arguments. Furthermore, ``c`` and ``e`` are required keyword +arguments, since they do not have a default value. + +If the parameter name after the ``*`` is omitted, the function will not accept any +extra positional arguments, e.g.:: + + def g(a, b, *, c, d): + ... + +takes exactly two positional parameters and has two required keyword parameters. + +Built-in Functions +------------------ + +Cython compiles calls to the following built-in functions into direct calls to +the corresponding Python/C API routines, making them particularly fast. + ++------------------------------+-------------+----------------------------+ +| Function and arguments | Return type | Python/C API Equivalent | ++==============================+=============+============================+ +| abs(obj) | object | PyNumber_Absolute | ++------------------------------+-------------+----------------------------+ +| delattr(obj, name) | int | PyObject_DelAttr | ++------------------------------+-------------+----------------------------+ +| dir(obj) | object | PyObject_Dir | +| getattr(obj, name) (Note 1) | | | +| getattr3(obj, name, default) | | | ++------------------------------+-------------+----------------------------+ +| hasattr(obj, name) | int | PyObject_HasAttr | ++------------------------------+-------------+----------------------------+ +| hash(obj) | int | PyObject_Hash | ++------------------------------+-------------+----------------------------+ +| intern(obj) | object | PyObject_InternFromString | ++------------------------------+-------------+----------------------------+ +| isinstance(obj, type) | int | PyObject_IsInstance | ++------------------------------+-------------+----------------------------+ +| issubclass(obj, type) | int | PyObject_IsSubclass | ++------------------------------+-------------+----------------------------+ +| iter(obj) | object | PyObject_GetIter | ++------------------------------+-------------+----------------------------+ +| len(obj) | Py_ssize_t | PyObject_Length | ++------------------------------+-------------+----------------------------+ +| pow(x, y, z) (Note 2) | object | PyNumber_Power | ++------------------------------+-------------+----------------------------+ +| reload(obj) | object | PyImport_ReloadModule | ++------------------------------+-------------+----------------------------+ +| repr(obj) | object | PyObject_Repr | ++------------------------------+-------------+----------------------------+ +| setattr(obj, name) | void | PyObject_SetAttr | ++------------------------------+-------------+----------------------------+ + +Note 1: There are two different functions corresponding to the Python +:func:`getattr` depending on whether a third argument is used. In a Python +context, they both evaluate to the Python :func:`getattr` function. + +Note 2: Only the three-argument form of :func:`pow` is supported. Use the +``**`` operator otherwise. + +Only direct function calls using these names are optimised. If you do +something else with one of these names that assumes it's a Python object, such +as assign it to a Python variable, and later call it, the call will be made as +a Python function call. + +Conditional Compilation +----------------------- + +Some features are available for conditional compilation and compile-time +constants within a Cython source file. + +Compile-Time Definitions +^^^^^^^^^^^^^^^^^^^^^^^^ + +A compile-time constant can be defined using the DEF statement:: + + DEF FavouriteFood = "spam" + DEF ArraySize = 42 + DEF OtherArraySize = 2 * ArraySize + 17 + +The right-hand side of the ``DEF`` must be a valid compile-time expression. +Such expressions are made up of literal values and names defined using ``DEF`` +statements, combined using any of the Python expression syntax. + +The following compile-time names are predefined, corresponding to the values +returned by :func:``os.uname``. + + UNAME_SYSNAME, UNAME_NODENAME, UNAME_RELEASE, + UNAME_VERSION, UNAME_MACHINE + +The following selection of builtin constants and functions are also available: + + None, True, False, + abs, bool, chr, cmp, complex, dict, divmod, enumerate, + float, hash, hex, int, len, list, long, map, max, min, + oct, ord, pow, range, reduce, repr, round, slice, str, + sum, tuple, xrange, zip + +A name defined using ``DEF`` can be used anywhere an identifier can appear, +and it is replaced with its compile-time value as though it were written into +the source at that point as a literal. For this to work, the compile-time +expression must evaluate to a Python value of type ``int``, ``long``, +``float`` or ``str``.:: + + cdef int a1[ArraySize] + cdef int a2[OtherArraySize] + print "I like", FavouriteFood + +Conditional Statements +^^^^^^^^^^^^^^^^^^^^^^ + +The ``IF`` statement can be used to conditionally include or exclude sections +of code at compile time. It works in a similar way to the ``#if`` preprocessor +directive in C.:: + + IF UNAME_SYSNAME == "Windows": + include "icky_definitions.pxi" + ELIF UNAME_SYSNAME == "Darwin": + include "nice_definitions.pxi" + ELIF UNAME_SYSNAME == "Linux": + include "penguin_definitions.pxi" + ELSE: + include "other_definitions.pxi" + +The ``ELIF`` and ``ELSE`` clauses are optional. An ``IF`` statement can appear +anywhere that a normal statement or declaration can appear, and it can contain +any statements or declarations that would be valid in that context, including +``DEF`` statements and other ``IF`` statements. + +The expressions in the ``IF`` and ``ELIF`` clauses must be valid compile-time +expressions as for the ``DEF`` statement, although they can evaluate to any +Python value, and the truth of the result is determined in the usual Python +way. + diff --git a/docs/limitations.rst b/docs/limitations.rst new file mode 100644 index 00000000..4985e25e --- /dev/null +++ b/docs/limitations.rst @@ -0,0 +1,69 @@ +.. _cython-limitations-label: + +Limitations +=========== + +Unsupported Python features +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Cython is not quite a full superset of Python. The following restrictions apply: + +* Function definitions (whether using ``def`` or ``cdef``) cannot be nested within + other function definitions. +* Class definitions can only appear at the top level of a module, + not inside a function. +* The ``import *`` form of import is not allowed anywhere (other forms of the + import statement are fine, though). +* Generators cannot be defined in Cython. +* The ``globals()`` and ``locals()`` functions cannot be used. + +The above restrictions will most likely remain, since removing them would be +difficult and they're not really needed for Cython's intended applications. + +There are also some temporary limitations, which may eventually be lifted, including: + +* Class and function definitions cannot be placed inside control structures. +* There is no support for Unicode. +* Special methods of extension types cannot have functioning docstrings. +* The use of string literals as comments is not recommended at present, + because Cython doesn't optimize them away, and won't even accept them in places + where executable statements are not allowed. + +Semantic differences between Python and Cython +---------------------------------------------- + +Behaviour of class scopes +^^^^^^^^^^^^^^^^^^^^^^^^^ + +In Python, referring to a method of a class inside the class definition, i.e. +while the class is being defined, yields a plain function object, but in +Cython it yields an unbound method [#]_. A consequence of this is that the +usual idiom for using the ``classmethod`` and ``staticmethod`` functions, +e.g.:: + + class Spam: + + def method(cls): + ... + + method = classmethod(method) + +will not work in Cython. This can be worked around by defining the function +outside the class, and then assigning the result of ``classmethod`` or +``staticmethod`` inside the class, i.e.:: + + def Spam_method(cls): + ... + + class Spam: + + method = classmethod(Spam_method) + +.. rubric:: Footnotes + +.. [#] The reason for the different behaviour of class scopes is that + Cython-defined Python functions are PyCFunction objects, not PyFunction + objects, and are not recognised by the machinery that creates a bound + or unbound method when a function is extracted from a class. To get + around this, Cython wraps each method in an unbound method object itself + before storing it in the class's dictionary. diff --git a/docs/overview.rst b/docs/overview.rst new file mode 100644 index 00000000..6e3610d9 --- /dev/null +++ b/docs/overview.rst @@ -0,0 +1,152 @@ +.. _overview-label: + +******** +Overview +******** + +A language for writing Python extension modules + +What is Cython all about? +========================= + +Cython is a language specially designed for writing Python extension modules. +It's designed to bridge the gap between the nice, high-level, easy-to-use +world of Python and the messy, low-level world of C. + +You may be wondering why anyone would want a special language for this. Python +is really easy to extend using C or C++, isn't it? Why not just write your +extension modules in one of those languages? + +Well, if you've ever written an extension module for Python, you'll know that +things are not as easy as all that. First of all, there is a fair bit of +boilerplate code to write before you can even get off the ground. Then you're +faced with the problem of converting between Python and C data types. For the +basic types such as numbers and strings this is not too bad, but anything more +elaborate and you're into picking Python objects apart using the Python/C API +calls, which requires you to be meticulous about maintaining reference counts, +checking for errors at every step and cleaning up properly if anything goes +wrong. Any mistakes and you have a nasty crash that's very difficult to debug. + +Various tools have been developed to ease some of the burdens of producing +extension code, of which perhaps SWIG is the best known. SWIG takes a +definition file consisting of a mixture of C code and specialised +declarations, and produces an extension module. It writes all the boilerplate +for you, and in many cases you can use it without knowing about the Python/C +API. But you need to use API calls if any substantial restructuring of the +data is required between Python and C. + +What's more, SWIG gives you no help at all if you want to create a new +built-in Python type. It will generate pure-Python classes which wrap (in a +slightly unsafe manner) pointers to C data structures, but creation of true +extension types is outside its scope. + +Another notable attempt at making it easier to extend Python is PyInline , +inspired by a similar facility for Perl. PyInline lets you embed pieces of C +code in the midst of a Python file, and automatically extracts them and +compiles them into an extension. But it only converts the basic types +automatically, and as with SWIG, it doesn't address the creation of new +Python types. + +Cython aims to go far beyond what any of these previous tools provides. Cython +deals with the basic types just as easily as SWIG, but it also lets you write +code to convert between arbitrary Python data structures and arbitrary C data +structures, in a simple and natural way, without knowing anything about the +Python/C API. That's right -- nothing at all! Nor do you have to worry about +reference counting or error checking -- it's all taken care of automatically, +behind the scenes, just as it is in interpreted Python code. And what's more, +Cython lets you define new built-in Python types just as easily as you can +define new classes in Python. + +Sound too good to be true? Read on and find out how it's done. + +The Basics of Cython +==================== + +The fundamental nature of Cython can be summed up as follows: Cython is Python +with C data types. + +Cython is Python: Almost any piece of Python code is also valid Cython code. +(There are a few :ref:`cython-limitations-label`, but this approximation will +serve for now.) The Cython compiler will convert it into C code which makes +equivalent calls to the Python/C API. + +But Cython is much more than that, because parameters and variables can be +declared to have C data types. Code which manipulates Python values and C +values can be freely intermixed, with conversions occurring automatically +wherever possible. Reference count maintenance and error checking of Python +operations is also automatic, and the full power of Python's exception +handling facilities, including the try-except and try-finally statements, is +available to you -- even in the midst of manipulating C data. + +Here's a small example showing some of what can be done. It's a routine for +finding prime numbers. You tell it how many primes you want, and it returns +them as a Python list. + +:file:`primes.pyx`: + +.. code-block:: none + :linenos: + + def primes(int kmax): + cdef int n, k, i + cdef int p[1000] + result = [] + if kmax > 1000: + kmax = 1000 + k = 0 + n = 2 + while k < kmax: + i = 0 + while i < k and n % p[i] != 0: + i = i + 1 + if i == k: + p[k] = n + k = k + 1 + result.append(n) + n = n + 1 + return result + +You'll see that it starts out just like a normal Python function definition, +except that the parameter ``kmax`` is declared to be of type ``int`` . This +means that the object passed will be converted to a C integer (or a +``TypeError.`` will be raised if it can't be). + +Lines 2 and 3 use the ``cdef`` statement to define some local C variables. +Line 4 creates a Python list which will be used to return the result. You'll +notice that this is done exactly the same way it would be in Python. Because +the variable result hasn't been given a type, it is assumed to hold a Python +object. + +Lines 7-9 set up for a loop which will test candidate numbers for primeness +until the required number of primes has been found. Lines 11-12, which try +dividing a candidate by all the primes found so far, are of particular +interest. Because no Python objects are referred to, the loop is translated +entirely into C code, and thus runs very fast. + +When a prime is found, lines 14-15 add it to the p array for fast access by +the testing loop, and line 16 adds it to the result list. Again, you'll notice +that line 16 looks very much like a Python statement, and in fact it is, with +the twist that the C parameter ``n`` is automatically converted to a Python +object before being passed to the append method. Finally, at line 18, a normal +Python return statement returns the result list. + +Compiling primes.pyx with the Cython compiler produces an extension module +which we can try out in the interactive interpreter as follows:: + + >>> import primes + >>> primes.primes(10) + [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] + +See, it works! And if you're curious about how much work Cython has saved you, +take a look at the C code generated for this module. + +Language Details +================ + +For more about the Cython language, see :ref:`language-basics-label`. + +Future Plans +============ +Cython is not finished. Substantial tasks remaining. See +:ref:`cython-limitations-label` for a current list. + diff --git a/docs/pyrex_differences.rst b/docs/pyrex_differences.rst new file mode 100644 index 00000000..24d0fe1f --- /dev/null +++ b/docs/pyrex_differences.rst @@ -0,0 +1,276 @@ +Differences between Cython and Pyrex +==================================== + +Package names and cross-directory imports +----------------------------------------- + +Just like in python. + +List Comprehensions +------------------- + +`[expr(x) for x in A]` is now available, implementing the full specification +at http://www.python.org/dev/peps/pep-0202/ . Looping is optimized if ``A`` is +a list. Also, use the :keyword:`for` ... :keyword:`from` syntax too, e.g.:: + + [i*i for i from 0 <= i < 10] + +In-place operators +------------------ + +The following is now legal:: + + x += 10 + +for all single-character operators, for both python and :keyword:`cdef` variables. Side +effects behave properly, i.e. for:: + + L[foo()] += bar() + +:func:`foo` is called exactly once, before :func:`bar`. + +Conditional expressions "x if b else y" (python 2.5) +---------------------------------------------------- + +Conditional expressions as described in +http://www.python.org/dev/peps/pep-0308/:: + + X if C else Y + +Only one of ``X`` and ``Y`` is evaluated, (depending on the value of C). + +cdef inline +----------- + +Module level functions can now be declared inline, with the :keyword:`inline` +keyword passed on to the C compiler. These can be as fast as macros.:: + + cdef inline int something_fast(int a, int b): + return a*a + b + +Note that class-level :keyword:`cdef` functions are handled via a virtual +function table, so the compiler won't be able to inline them in almost all +cases. + +Assignment on declaration (e.g. "cdef int spam = 5") +---------------------------------------------------- + +In Pyrex, one must write:: + + cdef int i, j, k + i = 2 + j = 5 + k = 7 + +Now, with cython, one can write:: + + cdef int i = 2, j = 5, k = 7 + +The expression on the right hand side can be arbitrarily complicated, e.g.:: + + cdef int n = python_call(foo(x,y), a + b + c) - 32 + + +'by' expression in for loop (e.g. "for i from 0 <= i < 10 by 2") +---------------------------------------------------------------- + +:: + + for i from 0 <= i < 10 by 2: + print i + + +yields:: + + 0 + 2 + 4 + 6 + 8 + + +Boolean int type (e.g. it acts like a c int, but coerces to/from python as a boolean) +------------------------------------------------------------------------------------- + +In C, ints are used for truth values. In python, any object can be used as a +truth value (using the :meth:`__nonzero__` method, but the canonical choices +are the two boolean objects ``True`` and ``False``. The :keyword:`bint` of +"boolean int" object is compiled to a C int, but get coerced to and from +Cython as booleans. The return type of comparisons and several builtins is a +:ctype:`bint` as well. This allows one to avoid having to wrap things in +:func:`bool()`. For example, one can write:: + + def is_equal(x): + return x == y + +which would return ``1`` or ``0`` in Pyrex, but returns ``True`` or ``False`` in +python. One can declare variables and return values for functions to be of the +:ctype:`bint` type. For example:: + + cdef int i = x + Cdef bint b = x + +The first conversion would happen via ``x.__int__()`` whereas the second would +happen via ``x.__nonzero__()``. (Actually, if ``x`` is the python object +``True`` or ``False`` then no method call is made.) + +Executable class bodies +----------------------- + +Including a working :func:`classmethod`:: + + cdef class Blah: + def some_method(self): + print self + some_method = classmethod(some_method) + a = 2*3 + print "hi", a + +cpdef functions +--------------- + +Cython adds a third function type on top of the usual :keyword:`def` and +:keyword:`cdef`. If a function is declared :keyword:`cpdef` it can be called +from and overridden by both extension and normal python subclasses. You can +essentially think of a :keyword:`cpdef` method as a :keyword:`cdef` method + +some extras. (That's how it's implemented at least.) First, it creates a +:keyword:`def` method that does nothing but call the underlying +:keyword:`cdef` method (and does argument unpacking/coercion if needed). At +the top of the :keyword:`cdef` method a little bit of code is added to check +to see if it's overridden. Specifically, in pseudocode:: + + if type(self) has a __dict__: + foo = self.getattr('foo') + if foo is not wrapper_foo: + return foo(args) + [cdef method body] + +To detect whether or not a type has a dictionary, it just checks the +tp_dictoffset slot, which is ``NULL`` (by default) for extension types, but +non- null for instance classes. If the dictionary exists, it does a single +attribute lookup and can tell (by comparing pointers) whether or not the +returned result is actually a new function. If, and only if, it is a new +function, then the arguments packed into a tuple and the method called. This +is all very fast. A flag is set so this lookup does not occur if one calls the +method on the class directly, e.g.:: + + cdef class A: + cpdef foo(self): + pass + + x = A() + x.foo() # will check to see if overridden + A.foo(x) # will call A's implementation whether overridden or not + +See :ref:`early-binding-speed-label` for explanation and usage tips. + +.. _automatic-range-conversion: + +(Optional) automatic range conversion +------------------------------------- + +:: + + $cython --convert-range + +This will convert statements of the form ``for i in range(...)`` to ``for i +from ...`` when ``i`` is any cdef'd integer type, and the direction (i.e. sign +of step) can be determined. + +.. warning:: + + This may change the semantics if the range causes + assignment to ``i`` to overflow. Specifically, if this option is set, an error + will be raised before the loop is entered, whereas without this option the loop + will execute until a overflowing value is encountered. + +More friendly type casting +-------------------------- + +In Pyrex, if one types ``x`` where ``x`` is a Python object, one will get +the memory address of ``x``. Likewise, if one types ``i`` where ``i`` +is a C int, one will get an "object" at location ``i`` in memory. This leads +to confusing results and segfaults. + +In Cython ``x`` will try and do a coercion (as would happen on assignment of +``x`` to a variable of type type) if exactly one of the types is a python object. +It does not stop one from casting where there is no conversion (though it will +emit a warning). If one really wants the address, cast to a ``void *`` first. + +As in Pyrex ``x`` will cast ``x`` to type `MyExtensionType` without any +type checking. Cython supports the syntax ```` to do the cast +with type checking (i.e. it will throw an error if ``x`` is not a (subclass of) +`MyExtensionType`. + +Optional arguments in cdef/cpdef functions +------------------------------------------ + +Cython now supports optional arguments for :keyword:`cdef` and +:keyword:`cpdef` functions. + +The syntax in the ``.pyx`` file remains as in Python, but one declares such +functions in the ``.pxd`` file by writing ``cdef foo(x=*)``. The number of +arguments may increase on subclassing, but the argument types and order must +remain the same. There is a slight performance penalty in some cases when a +cdef/cpdef function without any optional is overridden with one that does have +default argument values. + +For example, one can have the ``.pxd`` file:: + + cdef class A: + cdef foo(self) + cdef class B(A) + cdef foo(self, x=*) + cdef class C(B): + cpdef foo(self, x=*, int k=*) + +with corresponding ``.pyx`` file:: + + cdef class A: + cdef foo(self): + print "A" + cdef class B(A) + cdef foo(self, x=None) + print "B", x + cdef class C(B): + cpdef foo(self, x=True, int k=3) + print "C", x, k + +.. note:: + + this also demonstrates how :keyword:`cpdef` functions can override + :keyword:`cdef` functions. + +Function pointers in structs +---------------------------- + +Functions declared in :keyword:`structs` are automatically converted to +function pointers for convenience. + +C++ Exception handling +---------------------- + +:keyword:`cdef` functions can now be declared as:: + + cdef int foo(...) except + + cdef int foo(...) except +TypeError + cdef int foo(...) except +python_error_raising_function + +in which case a Python exception will be raised when a C++ error is caught. +See :ref:`wrapping-cplusplus-label` for more details. + +Synonyms +-------- + +``cdef import from`` means the same thing as ``cdef extern from`` + +Source code encoding +-------------------- + +-- TODO: add the links to the relevent PEPs + +Cython supports PEP 3120 and PEP 263, i.e. you can start your Cython source +file with an encoding comment and generally write your source code in UTF-8. +This impacts the encoding of byte strings and the conversion of unicode string +literals like ``u'abcd'`` to unicode objects. + diff --git a/docs/sharing_declarations.rst b/docs/sharing_declarations.rst new file mode 100644 index 00000000..a9fdc5de --- /dev/null +++ b/docs/sharing_declarations.rst @@ -0,0 +1,216 @@ +.. _sharing-declarations-label: + +Sharing Declarations Between Cython Modules +=========================================== + +This section describes a new set of facilities for making C declarations, +functions and extension types in one Cython module available for use in +another Cython module. These facilities are closely modelled on the Python +import mechanism, and can be thought of as a compile-time version of it. + +Definition and Implementation files +----------------------------------- + +A Cython module can be split into two parts: a definition file with a ``.pxd`` +suffix, containing C declarations that are to be available to other Cython +modules, and an implementation file with a ``.pyx`` suffix, containing +everything else. When a module wants to use something declared in another +module's definition file, it imports it using the :keyword:`cimport` +statement. What a Definition File contains A definition file can contain: + +* Any kind of C type declaration. +* extern C function or variable declarations. +* Declarations of C functions defined in the module. +* The definition part of an extension type (see below). + +It cannot contain any non-extern C variable declarations. + +It cannot contain the implementations of any C or Python functions, or any +Python class definitions, or any executable statements. + +.. note:: + + You don't need to (and shouldn't) declare anything in a declaration file + public in order to make it available to other Cython 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. + +What an Implementation File contains +------------------------------------ + +An implementation file can contain any kind of Cython 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). + +The cimport statement +--------------------- + +The :keyword:`cimport` 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:: + + cimport module [, module...] + + from module cimport name [as name] [, name [as name] ...] + +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. + +:file:`dishes.pxd`:: + + cdef enum otherstuff: + sausage, eggs, lettuce + + cdef struct spamdish: + int oz_of_spam + otherstuff filler + +:file:`restaurant.pyx`:: + + cimport dishes + from dishes cimport spamdish + + cdef void prepare(spamdish *d): + d.oz_of_spam = 42 + d.filler = dishes.sausage + + def serve(): + spamdish d + prepare(&d) + print "%d oz spam, filler no. %d" % (d->oz_of_spam, d->otherstuff) + +It is important to understand that the :keyword:`cimport` statement can only +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 import statement for it as well. + +The exception is that when you use :keyword:`cimport` 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 :keyword:`cimport` to import extension types is covered in more +detail below. + +Search paths for definition files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When you :keyword:`cimport` a module called ``modulename``, the Cython +compiler searches for a file called :file:`modulename.pxd` along the search +path for include files, as specified by ``-I`` command line options. + +Also, whenever you compile a file :file:`modulename.pyx`, the corresponding +definition file :file:`modulename.pxd` is first searched for along the same +path, and if found, it is processed before processing the ``.pyx`` file. + +Using cimport to resolve naming conflicts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :keyword:`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 :keyword:`cimport` that module. You can then +refer to the C functions by qualifying them with the name of the module. +Here's an example: + +:file:`c_lunch.pxd` :: + + cdef extern from "lunch.h": + void eject_tomato(float) + +:file:`lunch.pyx` :: + + cimport c_lunch + + def eject_tomato(float speed): + c_lunch.eject_tomato(speed) + +You don't need any :file:`c_lunch.pyx` file, because the only things defined +in :file:`c_lunch.pxd` are extern C entities. There won't be any actual +``c_lunch`` module at run time, but that doesn't matter; the +:file:`c_lunch.pxd` file has done its job of providing an additional namespace +at compile time. + +Sharing C Functions +=================== + +C functions defined at the top level of a module can be made available via +:keyword:`cimport` by putting headers for them in the ``.pxd`` file, for +example,: + +:file:`volume.pxd`: + +:file:`spammery.pyx`:: + + cdef float cube(float) + + from volume cimport cube + + def menu(description, size): + print description, ":", cube(size), \ + "cubic metres of spam" + + menu("Entree", 1) + menu("Main course", 3) + menu("Dessert", 2) + +:file:`volume.pyx`:: + + cdef float cube(float x): + return x * x * x + +.. note:: + + When a module exports a C function in this way, an object appears in the + module dictionary under the function's name. However, you can't make use of + this object from Python, nor can you use it from Cython using a normal import + statement; you have to use :keyword:`cimport`. + +Sharing Extension Types +======================= + +An extension type can be made available via :keyword:`cimport` by splitting +its definition into two parts, one in a definition file and the other in the +corresponding implementation file. + +The definition part of the extension type can only declare C attributes and C +methods, not Python methods, and it must declare all of that type's C +attributes and C methods. + +The implementation part must implement all of the C methods declared in the +definition part, and may not add any further C attributes. It may also define +Python methods. + +Here is an example of a module which defines and exports an extension type, +and another module which uses it.:: + + Shrubbing.pxd Shrubbing.pyx + cdef class Shrubbery: + cdef int width + cdef int length cdef class Shrubbery: + def __new__(self, int w, int l): + self.width = w + self.length = l + + def standard_shrubbery(): + return Shrubbery(3, 7) + Landscaping.pyx + cimport Shrubbing + import Shrubbing + + cdef Shrubbing.Shrubbery sh + sh = Shrubbing.standard_shrubbery() + print "Shrubbery size is %d x %d" % (sh.width, sh.height) + +Some things to note about this example: + +* There is a :keyword:`cdef` class Shrubbery declaration in both + :file:`Shrubbing.pxd` and :file:`Shrubbing.pyx`. When the Shrubbing module + is compiled, these two declarations are combined into one. +* In Landscaping.pyx, the :keyword:`cimport` Shrubbing declaration allows us + to refer to the Shrubbery type as :class:`Shrubbing.Shrubbery`. But it + doesn't bind the name Shrubbing in Landscaping's module namespace at run + time, so to access :func:`Shrubbing.standard_shrubbery` we also need to + ``import Shrubbing``. + diff --git a/docs/source_files_and_compilation.rst b/docs/source_files_and_compilation.rst new file mode 100644 index 00000000..e15d9503 --- /dev/null +++ b/docs/source_files_and_compilation.rst @@ -0,0 +1,37 @@ +.. TODO: Rewrite this to be more comprehensive, with examples! + +**************************** +Source Files and Compilation +**************************** + +Cython source file names consist of the name of the module followed by a +``.pyx`` extension, for example a module called primes would have a source +file named :file:`primes.pyx`. + +If your module is destined to live in a package, the source file name should +include the full dotted name that the module will eventually have. For +example, a module called primes that will be installed in a package called +numbers should have a source file called numbers.primes.pyx. This will ensure +that the :attr:`__name__` properties of the module and any classes defined in +it are set correctly. If you don't do this, you may find that pickling doesn't +work, among other problems. It also ensures that the Cython compiler has the +right idea about the layout of the module namespace, which can be important +when accessing extension types defined in other modules. + +Once you have written your ``.pyx`` file, there are a couple of ways of turning it +into an extension module. One way is to compile it manually with the Cython +compiler, e.g.:: + + $ cython primes.pyx + +This will produce a file called :file:`primes.c`, which then needs to be +compiled with the C compiler using whatever options are appropriate on your +platform for generating an extension module. There's a Makefile in the Demos +directory (called Makefile.nodistutils) that shows how to do this for Linux. + +The other, and probably better, way is to use the :mod:`distutils` extension +provided with Cython. See the :file:`setup.py` file in the Demos directory for an +example of how to use it. This method has the advantage of being +cross-platform -- the same setup file should work on any platform where +:mod:`distutils` can compile an +extension module. diff --git a/docs/wrapping_CPlusPlus.rst b/docs/wrapping_CPlusPlus.rst new file mode 100644 index 00000000..825b5852 --- /dev/null +++ b/docs/wrapping_CPlusPlus.rst @@ -0,0 +1,6 @@ +.. _wrapping-cplusplus-label: + +Wrapping C++ +============ + +TODO diff --git a/index.rst b/index.rst new file mode 100644 index 00000000..221d928d --- /dev/null +++ b/index.rst @@ -0,0 +1,32 @@ +.. Cython documentation master file, created by sphinx-quickstart on Fri Apr 25 12:49:32 2008. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Cython's documentation! +================================================ + +Contents: + +.. toctree:: + :maxdepth: 2 + + docs/overview + docs/language_basics + docs/extension_types + docs/sharing_declarations + docs/external_C_code + docs/wrapping_CPlusPlus + docs/source_files_and_compilation + docs/limitations + docs/pyrex_differences + docs/early_binding_for_speed + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +.. toctree:: +