EuroSciPy 2015, Stefan Behnel


In [1]:
%load_ext cython

In [2]:
import sys
import Cython
#print("Python %d.%d.%d %s %s" % sys.version_info)
#print("Cython %s" % Cython.__version__)

Building Cython modules


In [ ]:
# simple setup without elaborate dependencies
from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("*.pyx"),  # <- glob pattern
)

In [ ]:
# more complex case with per-module configuration
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension

ext_modules = [
    Extension(
        ["mypackage/mymodule.pyx"],
        ...  # configure C build + libraries here
    )]

setup(ext_modules = cythonize(ext_modules))

Functions and Coercion


In [3]:
%%cython

def pyfunc(x):
    return x + 1

def cyfunc(int x):
    return x + 1

cdef int cfunc(int x):
    return x + 1

cpdef cypyfunc(int x):
    y = cfunc(x + 1)
    return y * 2

In [4]:
pyfunc(2)


Out[4]:
3

In [5]:
cyfunc(2)


Out[5]:
3

In [6]:
cfunc(2)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-aad7450ab81e> in <module>()
----> 1 cfunc(2)

NameError: name 'cfunc' is not defined

In [7]:
cypyfunc(2)


Out[7]:
8

Static typing and type inference


In [8]:
import math

def sin(x):
    return math.sin(x)

In [9]:
%%cython -a
cimport libc.math

def sin(double x):
    return libc.math.sin(x)


Out[9]:
Cython: _cython_magic_e8d40d836d7eeffcab5c520a21184dd9.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

 1: cimport libc.math
 2: 
+3: def sin(double x):
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_e8d40d836d7eeffcab5c520a21184dd9_1sin(PyObject *__pyx_self, PyObject *__pyx_arg_x); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_e8d40d836d7eeffcab5c520a21184dd9_1sin = {"sin", (PyCFunction)__pyx_pw_46_cython_magic_e8d40d836d7eeffcab5c520a21184dd9_1sin, METH_O, 0};
static PyObject *__pyx_pw_46_cython_magic_e8d40d836d7eeffcab5c520a21184dd9_1sin(PyObject *__pyx_self, PyObject *__pyx_arg_x) {
  double __pyx_v_x;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sin (wrapper)", 0);
  assert(__pyx_arg_x); {
    __pyx_v_x = __pyx_PyFloat_AsDouble(__pyx_arg_x); if (unlikely((__pyx_v_x == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("_cython_magic_e8d40d836d7eeffcab5c520a21184dd9.sin", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_46_cython_magic_e8d40d836d7eeffcab5c520a21184dd9_sin(__pyx_self, ((double)__pyx_v_x));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_e8d40d836d7eeffcab5c520a21184dd9_sin(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_x) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("sin", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("_cython_magic_e8d40d836d7eeffcab5c520a21184dd9.sin", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple_ = PyTuple_Pack(2, __pyx_n_s_x, __pyx_n_s_x); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_e8d40d836d7eeffcab5c520a21184dd9_1sin, NULL, __pyx_n_s_cython_magic_e8d40d836d7eeffcab); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_sin, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+4:     return libc.math.sin(x)
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyFloat_FromDouble(sin(__pyx_v_x)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

In [10]:
%%cython
def local_variables(x):
    cdef int i = 5, ix = x
    print(i * ix)
    return (i + ix) // 2

In [11]:
local_variables(2)


10
Out[11]:
3

Exercise: optimise Python code into C code

Optimise this code so that it compiles to plain C code but uses as few type declarations as possible.


In [12]:
import math

def py_circular_distance(radius, lon1, lat1, lon2, lat2):
    x = math.pi/180.0
    a = (90.0-lat1) * x
    b = (90.0-lat2) * x
    theta = (lon2-lon1) * x
    c = math.acos((math.cos(a)*math.cos(b)) + (math.sin(a)*math.sin(b)*math.cos(theta)))
    return radius*c

In [13]:
%%cython -a
cimport libc.math as math

def cy_circular_distance(double radius, double lon1, double lat1, double lon2, double lat2):
    x = math.M_PI/180.0
    a = (90.0-lat1) * x
    b = (90.0-lat2) * x
    theta = (lon2-lon1) * x
    c = math.acos((math.cos(a)*math.cos(b)) + (math.sin(a)*math.sin(b)*math.cos(theta)))
    return radius*c


Out[13]:
Cython: _cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

 1: cimport libc.math as math
 2: 
+3: def cy_circular_distance(double radius, double lon1, double lat1, double lon2, double lat2):
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4_1cy_circular_distance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4_1cy_circular_distance = {"cy_circular_distance", (PyCFunction)__pyx_pw_46_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4_1cy_circular_distance, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_46_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4_1cy_circular_distance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  double __pyx_v_radius;
  double __pyx_v_lon1;
  double __pyx_v_lat1;
  double __pyx_v_lon2;
  double __pyx_v_lat2;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("cy_circular_distance (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_radius,&__pyx_n_s_lon1,&__pyx_n_s_lat1,&__pyx_n_s_lon2,&__pyx_n_s_lat2,0};
    PyObject* values[5] = {0,0,0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_radius)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        case  1:
        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lon1)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("cy_circular_distance", 1, 5, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
        }
        case  2:
        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lat1)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("cy_circular_distance", 1, 5, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
        }
        case  3:
        if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lon2)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("cy_circular_distance", 1, 5, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
        }
        case  4:
        if (likely((values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lat2)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("cy_circular_distance", 1, 5, 5, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "cy_circular_distance") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
    }
    __pyx_v_radius = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_radius == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
    __pyx_v_lon1 = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_lon1 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
    __pyx_v_lat1 = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_lat1 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
    __pyx_v_lon2 = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_lon2 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
    __pyx_v_lat2 = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_lat2 == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("cy_circular_distance", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
  __pyx_L3_error:;
  __Pyx_AddTraceback("_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4.cy_circular_distance", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_46_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4_cy_circular_distance(__pyx_self, __pyx_v_radius, __pyx_v_lon1, __pyx_v_lat1, __pyx_v_lon2, __pyx_v_lat2);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4_cy_circular_distance(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_radius, double __pyx_v_lon1, double __pyx_v_lat1, double __pyx_v_lon2, double __pyx_v_lat2) {
  double __pyx_v_x;
  double __pyx_v_a;
  double __pyx_v_b;
  double __pyx_v_theta;
  double __pyx_v_c;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("cy_circular_distance", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4.cy_circular_distance", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple_ = PyTuple_Pack(10, __pyx_n_s_radius, __pyx_n_s_lon1, __pyx_n_s_lat1, __pyx_n_s_lon2, __pyx_n_s_lat2, __pyx_n_s_x, __pyx_n_s_a, __pyx_n_s_b, __pyx_n_s_theta, __pyx_n_s_c); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_1bb61b3ca631ffd4895e85b4ddcdf8b4_1cy_circular_distance, NULL, __pyx_n_s_cython_magic_1bb61b3ca631ffd489); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_cy_circular_distance, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+4:     x = math.M_PI/180.0
  __pyx_v_x = (M_PI / 180.0);
+5:     a = (90.0-lat1) * x
  __pyx_v_a = ((90.0 - __pyx_v_lat1) * __pyx_v_x);
+6:     b = (90.0-lat2) * x
  __pyx_v_b = ((90.0 - __pyx_v_lat2) * __pyx_v_x);
+7:     theta = (lon2-lon1) * x
  __pyx_v_theta = ((__pyx_v_lon2 - __pyx_v_lon1) * __pyx_v_x);
+8:     c = math.acos((math.cos(a)*math.cos(b)) + (math.sin(a)*math.sin(b)*math.cos(theta)))
  __pyx_v_c = acos(((cos(__pyx_v_a) * cos(__pyx_v_b)) + ((sin(__pyx_v_a) * sin(__pyx_v_b)) * cos(__pyx_v_theta))));
+9:     return radius*c
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_radius * __pyx_v_c)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

In [14]:
print(py_circular_distance(10, 1.2, 2, 2, 4.3))
print(cy_circular_distance(10, 1.2, 2, 2, 4.3))


0.424943087932
0.424943087932

In [15]:
%timeit py_circular_distance(10, 1.2, 2, 2, 4.3)


The slowest run took 8.66 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 1.05 µs per loop

In [16]:
%timeit cy_circular_distance(10, 1.2, 2, 2, 4.3)


The slowest run took 14.79 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 210 ns per loop

Calling C functions


In [17]:
%%cython -a
# libc math functions
from libc cimport math

print( math.sin(math.M_PI / 2) )


1.0
Out[17]:
Cython: _cython_magic_f4f6e6b93544e557bcf370d9ff8a211c.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

 1: # libc math functions
 2: from libc cimport math
 3: 
+4: print( math.sin(math.M_PI / 2) )
  __pyx_t_1 = PyFloat_FromDouble(sin((M_PI / 2.0))); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (__Pyx_PrintOne(0, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

In [18]:
%%cython
# dynamic C memory allocation
from libc.stdlib cimport malloc, free

cdef int* cmem = <int*>malloc(22 * sizeof(int))
if not cmem:
    raise MemoryError()
free(cmem)

In [19]:
%%cython
# dynamic CPython heap memory allocation
from cpython.mem cimport PyMem_Malloc, PyMem_Free

cdef int* pymem = <int*>PyMem_Malloc(22 * sizeof(int))
if not pymem:
    raise MemoryError()
    
try:
    pymem[:] = [1,2,3]
    print( pymem[0] + pymem[2] )
finally:
    PyMem_Free(pymem)


4

Auto-wrapping C functions to Python


In [20]:
%%cython -a
from libc cimport math, stdlib
py_sin = math.sin
py_atoi = stdlib.atoi


Out[20]:
Cython: _cython_magic_7b7ff6dfa209858f1665a94608ddc60e.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

+1: from libc cimport math, stdlib
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+2: py_sin = math.sin
  __pyx_t_1 = __Pyx_CFunc_double____double____nogil_to_py(sin); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_py_sin, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+3: py_atoi = stdlib.atoi
  __pyx_t_1 = __Pyx_CFunc_int____const__char________nogil_to_py(atoi); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_py_atoi, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

In [21]:
py_sin(1/2)


Out[21]:
0.0

In [22]:
py_atoi(b'123')


Out[22]:
123

External libraries


In [23]:
%%cython
# distutils: include_dirs=/usr/include/luajit-2.0
# distutils: libraries=luajit-5.1

## distutils: include_dirs=/usr/include/lua5.1
## distutils: libraries=lua5.1

cdef extern from "lua.h":
    ctypedef struct lua_State
    lua_State *luaL_newstate ()
    void lua_close (lua_State *L)
    int luaL_loadbuffer (lua_State *L, char *buff, size_t sz, char *name)
    void lua_settop (lua_State *L, int idx)
    int lua_gettop (lua_State *L)
    int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc)
    int lua_type (lua_State *L, int idx)
    float lua_tonumber (lua_State *L, int idx)
    enum:
        LUA_TNUMBER
        LUA_MULTRET


def run_lua(code):
    cdef int result_status
    cdef float result

    if isinstance(code, unicode):
        code = code.encode('utf8')
    elif not isinstance(code, bytes):
        raise ValueError("code must be a string")

    # init Lua runtime
    L = luaL_newstate()
    if not L:
        raise MemoryError()

    try:
        # compile Lua code
        if luaL_loadbuffer(L, code, len(code), '<python>'):
            raise SyntaxError()

        # execute code
        if lua_pcall(L, 0, LUA_MULTRET, 0):
            raise RuntimeError()

        # convert return value (Lua number == float)
        assert lua_type(L, 1) == LUA_TNUMBER, "not a numeric return value"
        return lua_tonumber(L, 1)
    finally:
        lua_settop(L, 0)
        lua_close(L)


---------------------------------------------------------------------------
CompileError                              Traceback (most recent call last)
<ipython-input-23-df47a0dc49a2> in <module>()
----> 1 get_ipython().run_cell_magic(u'cython', u'', u'# distutils: include_dirs=/usr/include/luajit-2.0\n# distutils: libraries=luajit-5.1\n\n## distutils: include_dirs=/usr/include/lua5.1\n## distutils: libraries=lua5.1\n\ncdef extern from "lua.h":\n    ctypedef struct lua_State\n    lua_State *luaL_newstate ()\n    void lua_close (lua_State *L)\n    int luaL_loadbuffer (lua_State *L, char *buff, size_t sz, char *name)\n    void lua_settop (lua_State *L, int idx)\n    int lua_gettop (lua_State *L)\n    int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc)\n    int lua_type (lua_State *L, int idx)\n    float lua_tonumber (lua_State *L, int idx)\n    enum:\n        LUA_TNUMBER\n        LUA_MULTRET\n\n\ndef run_lua(code):\n    cdef int result_status\n    cdef float result\n\n    if isinstance(code, unicode):\n        code = code.encode(\'utf8\')\n    elif not isinstance(code, bytes):\n        raise ValueError("code must be a string")\n\n    # init Lua runtime\n    L = luaL_newstate()\n    if not L:\n        raise MemoryError()\n\n    try:\n        # compile Lua code\n        if luaL_loadbuffer(L, code, len(code), \'<python>\'):\n            raise SyntaxError()\n\n        # execute code\n        if lua_pcall(L, 0, LUA_MULTRET, 0):\n            raise RuntimeError()\n\n        # convert return value (Lua number == float)\n        assert lua_type(L, 1) == LUA_TNUMBER, "not a numeric return value"\n        return lua_tonumber(L, 1)\n    finally:\n        lua_settop(L, 0)\n        lua_close(L)')

/Users/markhoughton/anaconda/lib/python2.7/site-packages/IPython/core/interactiveshell.pyc in run_cell_magic(self, magic_name, line, cell)
   2262             magic_arg_s = self.var_expand(line, stack_depth)
   2263             with self.builtin_trap:
-> 2264                 result = fn(magic_arg_s, cell)
   2265             return result
   2266 

/Users/markhoughton/anaconda/lib/python2.7/site-packages/Cython/Build/IpythonMagic.pyc in cython(self, line, cell)

/Users/markhoughton/anaconda/lib/python2.7/site-packages/IPython/core/magic.pyc in <lambda>(f, *a, **k)
    191     # but it's overkill for just that one bit of state.
    192     def magic_deco(arg):
--> 193         call = lambda f, *a, **k: f(*a, **k)
    194 
    195         if callable(arg):

/Users/markhoughton/anaconda/lib/python2.7/site-packages/Cython/Build/IpythonMagic.pyc in cython(self, line, cell)
    276             build_extension.build_temp = os.path.dirname(pyx_file)
    277             build_extension.build_lib  = lib_dir
--> 278             build_extension.run()
    279             self._code_cache[key] = module_name
    280 

/Users/markhoughton/anaconda/lib/python2.7/distutils/command/build_ext.pyc in run(self)
    335 
    336         # Now actually compile and link everything.
--> 337         self.build_extensions()
    338 
    339     def check_extensions_list(self, extensions):

/Users/markhoughton/anaconda/lib/python2.7/distutils/command/build_ext.pyc in build_extensions(self)
    444 
    445         for ext in self.extensions:
--> 446             self.build_extension(ext)
    447 
    448     def build_extension(self, ext):

/Users/markhoughton/anaconda/lib/python2.7/distutils/command/build_ext.pyc in build_extension(self, ext)
    494                                          debug=self.debug,
    495                                          extra_postargs=extra_args,
--> 496                                          depends=ext.depends)
    497 
    498         # XXX -- this is a Vile HACK!

/Users/markhoughton/anaconda/lib/python2.7/distutils/ccompiler.pyc in compile(self, sources, output_dir, macros, include_dirs, debug, extra_preargs, extra_postargs, depends)
    572             except KeyError:
    573                 continue
--> 574             self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
    575 
    576         # Return *all* object filenames, not just the ones we just built.

/Users/markhoughton/anaconda/lib/python2.7/distutils/unixccompiler.pyc in _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts)
    120                        extra_postargs)
    121         except DistutilsExecError, msg:
--> 122             raise CompileError, msg
    123 
    124     def create_static_lib(self, objects, output_libname,

CompileError: command 'gcc' failed with exit status 1

In [ ]:
code = '''
function fib(i)
    if i > 2 then
        return fib(i-1) + fib(i-2)
    else
        return 1
    end
end
'''

run_lua(code + "return fib(10)")

In [ ]:
%%timeit bench = code + "return fib(24)"

run_lua(bench)

In [ ]:
# distutils: include_dirs=/usr/include/luajit-2.0
# distutils: libraries=luajit-5.1

C arrays


In [3]:
%%cython -a
def carrays():
    cdef int[10] a, b
    a[:5] = [1,2,3,4,5]
    b = a
    b[5:] = [6,7,8,9,10]

    for i in b[:3]:
        print(i+1)

    return b


Out[3]:
Cython: _cython_magic_5961852834b61f275af35b261f1b4a64.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

+01: def carrays():
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_5961852834b61f275af35b261f1b4a64_1carrays(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_5961852834b61f275af35b261f1b4a64_1carrays = {"carrays", (PyCFunction)__pyx_pw_46_cython_magic_5961852834b61f275af35b261f1b4a64_1carrays, METH_NOARGS, 0};
static PyObject *__pyx_pw_46_cython_magic_5961852834b61f275af35b261f1b4a64_1carrays(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("carrays (wrapper)", 0);
  __pyx_r = __pyx_pf_46_cython_magic_5961852834b61f275af35b261f1b4a64_carrays(__pyx_self);

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_5961852834b61f275af35b261f1b4a64_carrays(CYTHON_UNUSED PyObject *__pyx_self) {
  int __pyx_v_a[10];
  int __pyx_v_b[10];
  PyObject *__pyx_v_i = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("carrays", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_AddTraceback("_cython_magic_5961852834b61f275af35b261f1b4a64.carrays", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_i);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple_ = PyTuple_Pack(3, __pyx_n_s_a, __pyx_n_s_b, __pyx_n_s_i); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_5961852834b61f275af35b261f1b4a64_1carrays, NULL, __pyx_n_s_cython_magic_5961852834b61f275a); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_carrays, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 02:     cdef int[10] a, b
+03:     a[:5] = [1,2,3,4,5]
  __pyx_t_1[0] = 1;
  __pyx_t_1[1] = 2;
  __pyx_t_1[2] = 3;
  __pyx_t_1[3] = 4;
  __pyx_t_1[4] = 5;
  memcpy(&(__pyx_v_a[0]), __pyx_t_1, sizeof(__pyx_v_a[0]) * (5));
+04:     b = a
  memcpy(&(__pyx_v_b[0]), __pyx_v_a, sizeof(__pyx_v_b[0]) * (10));
+05:     b[5:] = [6,7,8,9,10]
  __pyx_t_2[0] = 6;
  __pyx_t_2[1] = 7;
  __pyx_t_2[2] = 8;
  __pyx_t_2[3] = 9;
  __pyx_t_2[4] = 10;
  memcpy(&(__pyx_v_b[5]), __pyx_t_2, sizeof(__pyx_v_b[0]) * (5));
 06: 
+07:     for i in b[:3]:
  __pyx_t_4 = (__pyx_v_b + 3);
  for (__pyx_t_5 = __pyx_v_b; __pyx_t_5 < __pyx_t_4; __pyx_t_5++) {
    __pyx_t_3 = __pyx_t_5;
    __pyx_t_6 = __Pyx_PyInt_From_int((__pyx_t_3[0])); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_6);
    __pyx_t_6 = 0;
+08:         print(i+1)
    __pyx_t_6 = __Pyx_PyInt_AddObjC(__pyx_v_i, __pyx_int_1, 1, 0); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    __Pyx_GOTREF(__pyx_t_6);
    if (__Pyx_PrintOne(0, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  }
 09: 
+10:     return b
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_6 = __Pyx_carray_to_py_int(__pyx_v_b, 10); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_r = __pyx_t_6;
  __pyx_t_6 = 0;
  goto __pyx_L0;

In [4]:
carrays()


2
3
4
Out[4]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

C tuples


In [5]:
%%cython -a

def ctuples():
    cdef int a = 42
    cdef double b = a / 5.0

    cdef (int, double) t = (a, b)
    print(t[0])
    print(t[1])
    print(t)

    return t


Out[5]:
Cython: _cython_magic_7464125faea6c1b99d5f1e14b64d3824.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

 01: 
+02: def ctuples():
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_7464125faea6c1b99d5f1e14b64d3824_1ctuples(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_7464125faea6c1b99d5f1e14b64d3824_1ctuples = {"ctuples", (PyCFunction)__pyx_pw_46_cython_magic_7464125faea6c1b99d5f1e14b64d3824_1ctuples, METH_NOARGS, 0};
static PyObject *__pyx_pw_46_cython_magic_7464125faea6c1b99d5f1e14b64d3824_1ctuples(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("ctuples (wrapper)", 0);
  __pyx_r = __pyx_pf_46_cython_magic_7464125faea6c1b99d5f1e14b64d3824_ctuples(__pyx_self);

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_7464125faea6c1b99d5f1e14b64d3824_ctuples(CYTHON_UNUSED PyObject *__pyx_self) {
  int __pyx_v_a;
  double __pyx_v_b;
  __pyx_ctuple_int__and_double __pyx_v_t;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("ctuples", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("_cython_magic_7464125faea6c1b99d5f1e14b64d3824.ctuples", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple_ = PyTuple_Pack(3, __pyx_n_s_a, __pyx_n_s_b, __pyx_n_s_t); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_7464125faea6c1b99d5f1e14b64d3824_1ctuples, NULL, __pyx_n_s_cython_magic_7464125faea6c1b99d); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ctuples, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+03:     cdef int a = 42
  __pyx_v_a = 42;
+04:     cdef double b = a / 5.0
  __pyx_v_b = (__pyx_v_a / 5.0);
 05: 
+06:     cdef (int, double) t = (a, b)
  __pyx_t_1.f0 = __pyx_v_a;
  __pyx_t_1.f1 = __pyx_v_b;
  __pyx_v_t = __pyx_t_1;
+07:     print(t[0])
  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_t.f0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_2);
  if (__Pyx_PrintOne(0, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+08:     print(t[1])
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_t.f1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_2);
  if (__Pyx_PrintOne(0, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+09:     print(t)
  __pyx_t_2 = __pyx_convert__to_py___pyx_ctuple_int__and_double(__pyx_v_t); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_2);
  if (__Pyx_PrintOne(0, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 10: 
+11:     return t
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_2 = __pyx_convert__to_py___pyx_ctuple_int__and_double(__pyx_v_t); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

In [6]:
ctuples()


42
8.4
(42, 8.4)
Out[6]:
(42, 8.4)

C++


In [7]:
%%cython -a
# distutils: language=c++


from libcpp.vector cimport vector

def func():
    cdef vector[int] v
    v.push_back(10)
    return v


Out[7]:
Cython: _cython_magic_326f039f701a788ca13f07367dd31dc7.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

+1: # distutils: language=c++
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 2: 
 3: 
 4: from libcpp.vector cimport vector
 5: 
+6: def func():
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_326f039f701a788ca13f07367dd31dc7_1func(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_326f039f701a788ca13f07367dd31dc7_1func = {"func", (PyCFunction)__pyx_pw_46_cython_magic_326f039f701a788ca13f07367dd31dc7_1func, METH_NOARGS, 0};
static PyObject *__pyx_pw_46_cython_magic_326f039f701a788ca13f07367dd31dc7_1func(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("func (wrapper)", 0);
  __pyx_r = __pyx_pf_46_cython_magic_326f039f701a788ca13f07367dd31dc7_func(__pyx_self);

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_326f039f701a788ca13f07367dd31dc7_func(CYTHON_UNUSED PyObject *__pyx_self) {
  std::vector<int>  __pyx_v_v;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("func", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("_cython_magic_326f039f701a788ca13f07367dd31dc7.func", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple_ = PyTuple_Pack(1, __pyx_n_s_v); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_326f039f701a788ca13f07367dd31dc7_1func, NULL, __pyx_n_s_cython_magic_326f039f701a788ca1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_func, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 7:     cdef vector[int] v
+8:     v.push_back(10)
  try {
    __pyx_v_v.push_back(10);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
+9:     return v
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_convert_vector_to_py_int(__pyx_v_v); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

In [8]:
func()


Out[8]:
[10]

In [9]:
%%cython -a
# distutils: language=c++

from libcpp.vector cimport vector

cdef class Integers:
    cdef vector[int] _values

    def add(self, int value):
        self._values.push_back(value)

    def __repr__(self):
        return repr(self._values)


Out[9]:
Cython: _cython_magic_a223d64801b6e0d831b95db768b53ac0.pyx

Generated by Cython 0.23.1

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

+01: # distutils: language=c++
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 02: 
 03: from libcpp.vector cimport vector
 04: 
 05: cdef class Integers:
 06:     cdef vector[int] _values
 07: 
+08:     def add(self, int value):
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_1add(PyObject *__pyx_v_self, PyObject *__pyx_arg_value); /*proto*/
static PyObject *__pyx_pw_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_1add(PyObject *__pyx_v_self, PyObject *__pyx_arg_value) {
  int __pyx_v_value;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("add (wrapper)", 0);
  assert(__pyx_arg_value); {
    __pyx_v_value = __Pyx_PyInt_As_int(__pyx_arg_value); if (unlikely((__pyx_v_value == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("_cython_magic_a223d64801b6e0d831b95db768b53ac0.Integers.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_add(((struct __pyx_obj_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_Integers *)__pyx_v_self), ((int)__pyx_v_value));
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_add(struct __pyx_obj_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_Integers *__pyx_v_self, int __pyx_v_value) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("add", 0);
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_AddTraceback("_cython_magic_a223d64801b6e0d831b95db768b53ac0.Integers.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+09:         self._values.push_back(value)
  try {
    __pyx_v_self->_values.push_back(__pyx_v_value);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  }
 10: 
+11:     def __repr__(self):
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_3__repr__(PyObject *__pyx_v_self); /*proto*/
static PyObject *__pyx_pw_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_3__repr__(PyObject *__pyx_v_self) {
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0);
  __pyx_r = __pyx_pf_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_2__repr__(((struct __pyx_obj_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_Integers *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_8Integers_2__repr__(struct __pyx_obj_46_cython_magic_a223d64801b6e0d831b95db768b53ac0_Integers *__pyx_v_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__repr__", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("_cython_magic_a223d64801b6e0d831b95db768b53ac0.Integers.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+12:         return repr(self._values)
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __pyx_convert_vector_to_py_int(__pyx_v_self->_values); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyObject_Repr(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

In [10]:
x = Integers()
x.add(2)
x.add(3)
x


Out[10]:
[2, 3]

In [ ]: