🤝 Like the tool? Help making it better! Your donation helps! 🤝
Note
This page uses two different syntax variants:
Cython specific cdef
syntax, which was designed to make type declarations
concise and easily readable from a C/C++ perspective.
Pure Python syntax which allows static Cython type declarations in pure Python code, following PEP-484 type hints and PEP 526 variable annotations.
To make use of C data types in Python syntax, you need to import the special
cython
module in the Python module that you want to compile, e.g.
import cython
If you use the pure Python syntax we strongly recommend you use a recent Cython 3 release, since significant improvements have been made here compared to the 0.29.x releases.
In addition to the .pyx
and .py
source files, Cython uses .pxd
files
which work like C header files – they contain Cython declarations
(and sometimes code sections) which are only meant for inclusion by
Cython modules. A .pxd
file is imported into a .pyx
module by
using the cimport
keyword.
.pxd
files have many use-cases:
They can be used for sharing external C declarations.
They can contain functions which are well suited for inlining by
the C compiler. Such functions should be marked inline
, example:
cdef inline int int_min(int a, int b):
return b if b < a else a
When accompanying an equally named .pyx
/ .py
file, they
provide a Cython interface to the Cython module so that other
Cython modules can communicate with it using a more efficient
protocol than the Python one.
In our integration example, we might break it up into .pxd
files like this:
Add a cmath.pxd
:
cdef extern from "math.h":
cpdef double sin(double x)
Then one would simply do
from cython.cimports.cmath import sin
Warning
The code provided above / on this page uses an external
native (non-Python) library through a cimport
(cython.cimports
).
Cython compilation enables this, but there is no support for this from
plain Python. Trying to run this code from Python (without compilation)
will fail when accessing the external library.
This is described in more detail in Calling C functions.
from cmath cimport sin
Add a integrate.pxd
so that other modules written in Cython
can define fast custom functions to integrate:
cdef class Function:
cpdef evaluate(self, double x)
cpdef integrate(Function f, double a, double b, int N)
Note that if you have a cdef class with attributes, the attributes must
be declared in the class declaration .pxd
file (if you use one), not
the .pyx
/ .py
file. The compiler will tell you about this.
Cython also supports __init__.pxd
files for declarations in package’s
namespaces, similar to __init__.py
files in Python.
Continuing the integration example, we could package the module as follows:
Place the module files in a directory tree as one usually would for Python:
CyIntegration/
├── __init__.py
├── __init__.pxd
├── integrate.py
└── integrate.pxd
CyIntegration/
├── __init__.pyx
├── __init__.pxd
├── integrate.pyx
└── integrate.pxd
In __init__.pxd
, use cimport
for any declarations that one
would want to be available from the package’s main namespace:
from cython.cimports.CyIntegration import integrate
from CyIntegration cimport integrate
Other modules would then be able to use cimport
on the package in
order to recursively gain faster, Cython access to the entire package
and the data declared in its modules:
from cython.cimports import CyIntegration
@cython.ccall
def do_integration(f: CyIntegration.integrate.Function):
return CyIntegration.integrate.integrate(f, 0., 2., 1)
Warning
The code provided above / on this page uses an external
native (non-Python) library through a cimport
(cython.cimports
).
Cython compilation enables this, but there is no support for this from
plain Python. Trying to run this code from Python (without compilation)
will fail when accessing the external library.
This is described in more detail in Calling C functions.
cimport CyIntegration
cpdef do_integration(CyIntegration.integrate.Function f):
return CyIntegration.integrate.integrate(f, 0., 2., 1)