Pure Python Mode
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 .py and .pyx files.
This is accomplished via special functions and decorators and an (optional) augmenting .pxd file.
Magic Attributes
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
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 & operator
cython.declare(x=cython.int, x_ptr=cython.p_int) x_ptr = cython.address(x)
sizeof emulates the sizeof operator. 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)
cdef struct MyStruct: int x int y double data cdef MyStruct a
union creates union types with exactly the same syntax as struct
typedef creates a new type
T = cython.typedef(cython.p_int) # ctypedef int* T
compiled is a special variable which is set to True when the compiler runs, and False in 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 .py file.
Augmenting .pxd
If a .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 a.pxd
cdef class A: cpdef foo(self, int i)
the file a.py
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"
Types
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 bint and 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[10]. A limited attempt is made to emulate these more complex types, but only so much can be done from the Python language.
Decorators
We have settled on @cython.cclass for the cdef class decorators, and @cython.cfunc and @cython.ccall for cdef and cpdef functions (respectively). http://codespeak.net/pipermail/cython-dev/2008-November/002925.html
