You can pass arguments to the C compiler using the keyword `extra_compile_args`

in your `setup.py`

. For example, this will not generate warnings:

```
from distutils.core
import setup
from Cython.Build
import cythonize
from distutils.extension
import Extension
import numpy
extensions = [
Extension("abc",
["abc.pyx"],
include_dirs = [numpy.get_include()],
extra_compile_args = ["-w"]
)
]
setup(
ext_modules = cythonize(extensions),
)
```

In Cython Tricks and Tips they explain that you need:

```
cdef extern from *:
pass
```

Then we compile the C file. This may vary according to your system, but the C file should be built like Python was built. Python documentation for writing extensions should have some details. On Linux this often means something like:,The main scenario considered is NumPy end-use rather than NumPy/SciPy development. The reason is that Cython is not (yet) able to support functions that are generic with respect to the number of dimensions in a high-level fashion. This restriction is much more severe for SciPy development than more specific, “end-user” functions. See the last section for more information on this.,If using another interactive command line environment than SAGE, like IPython or Python itself, it is important that you restart the process when you recompile the module. It is not enough to issue an “import” statement again.,This tutorial is aimed at NumPy users who have no experience with Cython at all. If you have some knowledge of Cython you may want to skip to the ‘’Efficient indexing’’ section.

pip install Cython

$ cd path / to / cython - distro $ path - to - sage / sage - python setup.py install

$ cython yourmod.pyx

$ gcc - shared - pthread - fPIC - fwrapv - O2 - Wall - fno - strict - aliasing - I / usr / include / python2 .7 - o yourmod.so yourmod.c

cimport numpy

```
def compute_np(array_1, array_2, a, b, c):
return np.clip(array_1, 2, 10) * a + array_2 * b + c
```

Since NumPy contains parts written in C and Cython that need to be compiled before use, make sure you have the necessary compilers and Python development headers installed - see Building from source. Building NumPy as of version 1.17 requires a C99 compliant compiler.,Having compiled code also means that importing NumPy from the development sources needs some additional steps, which are explained below. For the rest of this chapter we assume that you have set up your git repo as described in Git for development.,To build the development version of NumPy and run tests, spawn interactive shells with the Python import paths properly set up etc., do one of:,One simple way to achieve this is to install the released version in site-packages, by using pip or conda for example, and set up the development version in a virtual environment.

$ python runtests.py - v $ python runtests.py - v - s random $ python runtests.py - v - t numpy / core / tests / test_nditer.py::test_iter_c_order $ python runtests.py--ipython $ python runtests.py--python somescript.py $ python runtests.py--bench $ python runtests.py - g - m full

$ python runtests.py - t numpy / tests / test_scripts.py::test_f2py-- --pdb

`$ python runtests.py - v - t numpy / core / tests / test_multiarray.py-- - k "MatMul and not vector"`

$ python setup.py build_ext - i

```
$
export PYTHONPATH = $PWD
```

`$ set PYTHONPATH = /path/to / numpy`

NumPy arrays are the work horses of numerical computing with Python, and Cython allows one to work more efficiently with them.,As discussed in week 2, when working with NumPy arrays in Python one should avoid for-loops and indexing individual elements and instead try to writeoperations with NumPy arrays in a vectorized form. The reason is two-fold:overhead inherent to Python for-loops and overhead from indexing a NumPyarray. ,In order to create more efficient C-code for NumPy arrays, additionaldeclarations are needed. To start with, one uses the Cython cimportstatement for getting access to NumPy types: ,By declaring the type and dimensions of an array before actually creating it,Cython can access the NumPy array more efficiently:

`cimport numpy as cnp`

```
import numpy as np # Normal NumPy importcimport numpy as cnp # Import
for NumPY C - APIdef func(): # declarations can be made only in function scope cdef cnp.ndarray[cnp.int_t, ndim = 2] data data = np.empty((N, N), dtype = int)… for i in range(N): for j in range(N): data[i, j] = …# double loop is done in nearly C speed
```

```
import numpy as np # Normal NumPy importcimport numpy as cnp # Import
for NumPY C - APIcimport cython @cython.boundscheck(False) @cython.wraparound(False) def func(): # declarations can be made only in function scope cdef cnp.ndarray[cnp.int_t, ndim = 2] data data = np.empty((N, N), dtype = int)… for i in range(N): for j in range(N): data[i, j] = …# double loop is done in nearly C speed
```

`cimport numpy as cnpimport cython...@cython.boundscheck(False) @cython.wraparound(False) def compute_mandel(double cr, double ci, int N, double bound = 1.5, double lim = 1000., int cutoff = 1000000): cdef cnp.ndarray[cnp.int_t, ndim = 2] mandel mandel = np.empty((N, N), dtype = int) cdef cnp.ndarray[cnp.double_t, ndim = 1] grid_x grid_x = np.linspace(-bound, bound, N) cdef int i, j cdef double x, y t0 = time() for i in range(N): for j in range(N): x = grid_x[i] y = grid_x[j] mandel[i, j] = kernel(x, y, cr, ci, lim, cutoff) return mandel, time() - t0`