EuroPython 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__)
Python 3.5.0 beta 3
Cython 0.23.beta1

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

Function "JIT compiling"

In [8]:
# NOTE: Python code!

import cython

@cython.compile
def calc(a, b):
    for x in range(a):
        b += x
    return b
    
In [9]:
calc(10, 20)
Out[9]:
65
In [10]:
type(calc)
Out[10]:
Cython.Build.Inline.RuntimeCompiledFunction

Calling C functions

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

print( math.sin(math.M_PI / 2) )
1.0
Out[11]:
Cython: _cython_magic_7b59fd28fa04df04fc472da95cd2e5e6.pyx

Generated by Cython 0.23.beta1

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 [12]:
%%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 [13]:
%%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 [14]:
%%cython -a
from libc cimport math, stdlib
py_sin = math.sin
py_atoi = stdlib.atoi
Out[14]:
Cython: _cython_magic_ab2e08202c97f4fb1f1c8944ff80d90b.pyx

Generated by Cython 0.23.beta1

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 [15]:
py_sin(1/2)
Out[15]:
0.479425538604203
In [16]:
py_atoi(b'123')
Out[16]:
123

External libraries

In [17]:
%%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)
In [18]:
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)")
Out[18]:
55.0
In [19]:
%%timeit bench = code + "return fib(24)"

run_lua(bench)
100 loops, best of 3: 2.15 ms per loop
In [20]:
# distutils: include_dirs=/usr/include/luajit-2.0
# distutils: libraries=luajit-5.1

C arrays

In [21]:
%%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[21]:
Cython: _cython_magic_0a0700be7e736bc6c3dc54429e7b8a95.pyx

Generated by Cython 0.23.beta1

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_0a0700be7e736bc6c3dc54429e7b8a95_1carrays(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_1carrays = {"carrays", (PyCFunction)__pyx_pw_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_1carrays, METH_NOARGS, 0};
static PyObject *__pyx_pw_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_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_0a0700be7e736bc6c3dc54429e7b8a95_carrays(__pyx_self);

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

static PyObject *__pyx_pf_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_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_0a0700be7e736bc6c3dc54429e7b8a95.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_0a0700be7e736bc6c3dc54429e7b8a95_1carrays, NULL, __pyx_n_s_cython_magic_0a0700be7e736bc6c3); 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 [22]:
carrays()
2
3
4
Out[22]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

C tuples

In [23]:
%%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[23]:
Cython: _cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e.pyx

Generated by Cython 0.23.beta1

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_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples = {"ctuples", (PyCFunction)__pyx_pw_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples, METH_NOARGS, 0};
static PyObject *__pyx_pw_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_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_28b17313f2e630a40c1e37e0dbcc1e7e_ctuples(__pyx_self);

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

static PyObject *__pyx_pf_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_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_28b17313f2e630a40c1e37e0dbcc1e7e.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_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples, NULL, __pyx_n_s_cython_magic_28b17313f2e630a40c); 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 [24]:
ctuples()
42
8.4
(42, 8.4)
Out[24]:
(42, 8.4)

C++

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


from libcpp.vector cimport vector

def func():
    cdef vector[int] v
    v.push_back(10)
    return v
Out[25]:
Cython: _cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5.pyx

Generated by Cython 0.23.beta1

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_a1e5605f1fdd147ec2c410b3c5d592f5_1func(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_1func = {"func", (PyCFunction)__pyx_pw_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_1func, METH_NOARGS, 0};
static PyObject *__pyx_pw_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_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_a1e5605f1fdd147ec2c410b3c5d592f5_func(__pyx_self);

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

static PyObject *__pyx_pf_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_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_a1e5605f1fdd147ec2c410b3c5d592f5.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_a1e5605f1fdd147ec2c410b3c5d592f5_1func, NULL, __pyx_n_s_cython_magic_a1e5605f1fdd147ec2); 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 [26]:
func()
Out[26]:
[10]
In [27]:
%%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[27]:
Cython: _cython_magic_57278ffaa1a4383a1c5140c04c32e598.pyx

Generated by Cython 0.23.beta1

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_57278ffaa1a4383a1c5140c04c32e598_8Integers_1add(PyObject *__pyx_v_self, PyObject *__pyx_arg_value); /*proto*/
static PyObject *__pyx_pw_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_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_57278ffaa1a4383a1c5140c04c32e598.Integers.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_add(((struct __pyx_obj_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_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_57278ffaa1a4383a1c5140c04c32e598_8Integers_add(struct __pyx_obj_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_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_57278ffaa1a4383a1c5140c04c32e598.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_57278ffaa1a4383a1c5140c04c32e598_8Integers_3__repr__(PyObject *__pyx_v_self); /*proto*/
static PyObject *__pyx_pw_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_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_57278ffaa1a4383a1c5140c04c32e598_8Integers_2__repr__(((struct __pyx_obj_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_Integers *)__pyx_v_self));

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

static PyObject *__pyx_pf_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_2__repr__(struct __pyx_obj_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_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_57278ffaa1a4383a1c5140c04c32e598.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 [28]:
x = Integers()
x.add(2)
x.add(3)
x
Out[28]:
[2, 3]