Cython provides language constructs to let the same file be either interpreted or compiled. This is accomplished by the same "magic" module
cython that directives use and which must be imported. This is available for both
This is accomplished via special functions and decorators and an (optional) augmenting
The currently supported attributes of the
cython module are:
- declare declares a typed variable in the current scope, which can be used in place of the
cdef type var [= value]construct. This has two forms, the first as an assignment (useful as it creates a declaration in interpreted mode as well)
x = cython.declare(cython.int) # cdef int x y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721
and the second mode as a simple function call
cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y
- locals is a decorator that is used to specify the types of local variables in the function body (including any or all of the argument types)
@cython.locals(a=cython.double, b=cython.double, n=cython.p_double) def foo(a, b, x, y): ...
- address is used in place of the
cython.declare(x=cython.int, x_ptr=cython.p_int) x_ptr = cython.address(x)
- sizeof emulates the
sizeofoperator. It can take both types and expressions.
cython.declare(n=cython.longlong) print cython.sizeof(cython.longlong), cython.sizeof(n)
- struct can be used to create struct types.
MyStruct = cython.struct(x=cython.int, y=cython.int, data=cython.double) a = cython.declare(MyStruct)
is equivalent to the code
cdef struct MyStruct: int x int y double data cdef MyStruct a
struct construction and assignment can write as
a = MyStruct(x=5, y=6, data=2.5)
and note that one should not write
a = MyStruct(5, 6, 2.5)
since the field names are stored unordered in pure Python. (Though it works in Cython.)
- union creates union types with exactly the same syntax as
- typedef creates a new type
T = cython.typedef(cython.p_int) # ctypedef int* T
- compiled is a special variable which is set to
Truewhen the compiler runs, and
Falsein the interpreter. Thus the code
if cython.compiled: print "Yep, I'm compiled." else: print "Just a lowly interpreted script."
will behave differently depending on whether or not the code is loaded as a compiled
.so file or a plain
.pxd file is found with the same name as a
.py file, it will be searched for
cdef classes and
cdef/cpdef functions and methods. It will then convert the corresponding classes/functions/methods in the
.py file to be of the correct type. Thus if one had
cdef class A: cpdef foo(self, int i)
class A: def foo(self, i): print "Big" if i > 1000 else "Small"
would be interpreted as
cdef class A: cpdef foo(self, int i): print "Big" if i > 1000 else "Small"
cython module can also be imported and used within the augmenting .pxd file. This makes it possible to add types to a pure python file without changing the file itself. For example, the following python file
def dostuff(n): t = 0 for i in range(n): t += i return t
could be augmented with the following .pxd file
import cython @cython.locals(t = cython.int, i = cython.int) cpdef int dostuff(int n)
cython.locals decorator, the
cython.declare() function can also be used to add types to global variables in the augmenting .pxd file.
Note that normal Python (
def) functions cannot be declared in .pxd files, so it is currently impossible to override the types of Python functions in .pxd files if they use
**kwargs in their signature, for instance.
There are numerous types builtin to the
cython module. One has all the standard c types, namely
char, short, int, long, longlong as well as their unsigned versions
uchar, ushort, uint, ulong, ulonglong.
One also has
Py_ssize_t. For each type, one has pointer types
p_int, pp_int, ..., up to three levels deep in interpreted mode, and infinitely deep in compiled mode. The Python types
int, long and
bool are interpreted as c
int, long and
bint respectively. Also, the python types
list, dict, tuple, ... may be used, as well as any user defined types.
Pointer types may be constructed with
cython.pointer(cython.int), and arrays as
cython.int. A limited attempt is made to emulate these more complex types, but only so much can be done from the Python language.
We have settled on
@cython.cclass for the cdef class decorators, and
@cython.ccall for cdef and cpdef functions (respectively). http://codespeak.net/pipermail/cython-dev/2008-November/002925.html