What's new in Cython 0.22

Cython 0.22 is nearing completion and it's a major feature release, so here's a list of major improvements to Cython's type system.

C arrays have become first class citizens in Cython's type system. Previously, they behaved mostly just like pointers, as they do in C. The new release allows them to coerce to Python lists (by default) and tuples (when requested by the context). They can also be assigned by value, without the need for an explicit copy loop.

cdef int[3] x = [0, 1, 2]
cdef int[3] y = x
y[2] = 5
print(y)          # -> [0, 1, 5]
print(<tuple>x)   # -> (0, 1, 2)

cdef int[2][3] z = [x, y]
print(z)          # -> [[0, 1, 2], [0, 1, 5]]

Typed tuples were added. They behave like Python tuples and coerce from and to them at need, but support any C types for their arguments.

cdef int x = 1
cdef double y = 2

cdef (int*, double*) xy = (&x, &y)
ptr_a, ptr_b = xy
print(ptr_a[0], ptr_b[0])    # ->  1 2.0

cdef (int, double) ab = (ptr_a[0], ptr_b[0])
print(ab)                    # ->  (1, 2.0)

C/C++ functions have learned to auto-coerce to callable Python objects when used in an object context. Similarly, in order to provide a flat wrapper to an external C function, it is now sufficient to declare it as an external cpdef function in the module that should export it (or in the corresponding .pxd file).

cdef extern from "someheader.h":
    cpdef int cpfunc(int x, double y)
    cdef int cfunc(int x)

def use_cpfunc_from_cython():
    return cpfunc(1, 3.0)

def pass_cfunc_to_python():
    return cfunc

def use_from_python():
    >>> cpfunc(1, 3.0)
    >>> cfunc = pass_cfunc_to_python()
    >>> cfunc(4)