Python functions vs. C functions
C variable and type definitions
External declarations
Scope rules
Statements and expressions
Extension Types Special Methods Limitations
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 cdef statement. They take either Python objects or C values as parameters, and can return either Python objects or C values.
Within a Pyrex 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 Pyrex module must be declared as Python functions.
Parameters of either type of function can be declared to have C data types, using normal C declaration syntax. For example,
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.def spam(int i, char *s): ...cdef int eggs(unsigned long l, float f): ...
C functions, on the other hand, can have parameters of any type, since they're passed in directly using a normal C function call.
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:
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).cdef spamobjs(x, y): ...
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,
declares a parameter called int which is a Python object.cdef ftang(object int): ...
and C struct, union or enum types:cdef int i, j, k cdef float f, g[42], *h
Note that 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 writecdef struct Grail: int age float volumecdef union Food: char *spam float *eggscdef enum CheeseType: cheddar, edam, camembertcdef enum CheeseState: hard = 1 soft = 2 runny = 3
and notcdef Grail *gp
There is also a ctypedef statement for giving names to types, e.g.cdef struct Grail *gp # WRONG
ctypedef unsigned long ULongctypedef int *IntPtr
At some time in the future it is planned that Pyrex will be able to read C header files. In the meantime, to create interfaces to existing C code you will have to include extern definitions for all the outside C functions and variables that you use.cdef extern int spam_countercdef extern void order_spam(int tons)
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.
C operations which do not have direct Python equivalents are handled as follows:
There is no -> operator in Pyrex. Instead of p->x, use p.x
There is no * operator in Pyrex. Instead of *p, use p[0]
There is an an & operator, with the same semantics as in C
Type casts are written <type>value, for example: cdef char *p, float *q p = <char*>q
cdef class Shrubbery:As you can see, a Pyrex 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 __init__ as you would in Python.cdef int width, height
def __init__(self, w, h):
self.width = w
self.height = hdef describe(self):
print "This shrubbery is", self.width, \
"by", self.height, "cubits."
The main difference is that you can use the 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.
Some other differences between extension types and Python classes:
The set of attributes of an extension type 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.)
Attributes defined with cdef are only accessible from Pyrex code, not from Python code. (A way of defining Python-accessible attributes is planned, but not yet implemented. In the meantime, use accessor methods.)
To access the cdef-attributes of an extension type instance, the Pyrex 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 tell it by means of a declaration. For example, def widen_shrubbery(Shrubbery sh, extra_width):
sh.width = sh.width + extra_widthSome of the __xxx__ special methods behave differently from their Python counterparts, and some of them are named differently as well. See here for more information.
cdef class Shrubbery # forward declarationcdef class Shrubber:
cdef Shrubbery work_in_progresscdef class Shrubbery:
cdef Shrubber creator
There are also some temporary limitations which may eventually be lifted: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.
import * is not supported under any circumstances.
Generators are not supported.
There are probably also some other gaps which I can't think of at the moment.Class and function definitions cannot be placed inside control structures.
In-place operators (+=, etc) are not yet supported
List comprehensions are not yet supported