{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# EuroPython 2015, Stefan Behnel" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See http://consulting.behnel.de/" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python 3.5.0 beta 3\n", "Cython 0.23.beta1\n" ] } ], "source": [ "import sys\n", "import Cython\n", "print(\"Python %d.%d.%d %s %s\" % sys.version_info)\n", "print(\"Cython %s\" % Cython.__version__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Functions and Coercion" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%cython\n", "\n", "def pyfunc(x):\n", " return x + 1\n", "\n", "def cyfunc(int x):\n", " return x + 1\n", "\n", "cdef int cfunc(int x):\n", " return x + 1\n", "\n", "cpdef cypyfunc(int x):\n", " y = cfunc(x + 1)\n", " return y * 2" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pyfunc(2)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cyfunc(2)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "ename": "NameError", "evalue": "name 'cfunc' is not defined", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mcfunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mNameError\u001b[0m: name 'cfunc' is not defined" ] } ], "source": [ "cfunc(2)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cypyfunc(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Function \"JIT compiling\"" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# NOTE: Python code!\n", "\n", "import cython\n", "\n", "@cython.compile\n", "def calc(a, b):\n", " for x in range(a):\n", " b += x\n", " return b\n", " " ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "65" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "calc(10, 20)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "Cython.Build.Inline.RuntimeCompiledFunction" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(calc)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Calling C functions" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_7b59fd28fa04df04fc472da95cd2e5e6.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.beta1

\n", "

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

\n", "
 1: # libc math functions
\n", "
 2: from libc cimport math
\n", "
 3: 
\n", "
+4: print( math.sin(math.M_PI / 2) )
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (__Pyx_PrintOne(0, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "# libc math functions\n", "from libc cimport math\n", "\n", "print( math.sin(math.M_PI / 2) )\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%cython\n", "# dynamic C memory allocation\n", "from libc.stdlib cimport malloc, free\n", "\n", "cdef int* cmem = malloc(22 * sizeof(int))\n", "if not cmem:\n", " raise MemoryError()\n", "free(cmem)\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n" ] } ], "source": [ "%%cython\n", "# dynamic CPython heap memory allocation\n", "from cpython.mem cimport PyMem_Malloc, PyMem_Free\n", "\n", "cdef int* pymem = PyMem_Malloc(22 * sizeof(int))\n", "if not pymem:\n", " raise MemoryError()\n", " \n", "try:\n", " pymem[:] = [1,2,3]\n", " print( pymem[0] + pymem[2] )\n", "finally:\n", " PyMem_Free(pymem)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Auto-wrapping C functions to Python" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_ab2e08202c97f4fb1f1c8944ff80d90b.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.beta1

\n", "

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

\n", "
+1: from libc cimport math, stdlib
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+2: py_sin = math.sin
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+3: py_atoi = stdlib.atoi
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "from libc cimport math, stdlib\n", "py_sin = math.sin\n", "py_atoi = stdlib.atoi" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.479425538604203" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "py_sin(1/2)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "123" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "py_atoi(b'123')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# External libraries" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%cython\n", "# 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", "\n", "cdef 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", "\n", "def 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), ''):\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)\n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "55.0" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "code = '''\n", "function fib(i)\n", " if i > 2 then\n", " return fib(i-1) + fib(i-2)\n", " else\n", " return 1\n", " end\n", "end\n", "'''\n", "\n", "run_lua(code + \"return fib(10)\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100 loops, best of 3: 2.15 ms per loop\n" ] } ], "source": [ "%%timeit bench = code + \"return fib(24)\"\n", "\n", "run_lua(bench)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# distutils: include_dirs=/usr/include/luajit-2.0\n", "# distutils: libraries=luajit-5.1\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# C arrays" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_0a0700be7e736bc6c3dc54429e7b8a95.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.beta1

\n", "

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

\n", "
+01: def carrays():
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_1carrays(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_1carrays = {\"carrays\", (PyCFunction)__pyx_pw_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_1carrays, METH_NOARGS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_1carrays(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"carrays (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_carrays(__pyx_self);\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95_carrays(CYTHON_UNUSED PyObject *__pyx_self) {\n",
       "  int __pyx_v_a[10];\n",
       "  int __pyx_v_b[10];\n",
       "  PyObject *__pyx_v_i = NULL;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"carrays\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_6);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_0a0700be7e736bc6c3dc54429e7b8a95.carrays\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XDECREF(__pyx_v_i);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "/* … */\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 02:     cdef int[10] a, b
\n", "
+03:     a[:5] = [1,2,3,4,5]
\n", "
  __pyx_t_1[0] = 1;\n",
       "  __pyx_t_1[1] = 2;\n",
       "  __pyx_t_1[2] = 3;\n",
       "  __pyx_t_1[3] = 4;\n",
       "  __pyx_t_1[4] = 5;\n",
       "  memcpy(&(__pyx_v_a[0]), __pyx_t_1, sizeof(__pyx_v_a[0]) * (5));\n",
       "
+04:     b = a
\n", "
  memcpy(&(__pyx_v_b[0]), __pyx_v_a, sizeof(__pyx_v_b[0]) * (10));\n",
       "
+05:     b[5:] = [6,7,8,9,10]
\n", "
  __pyx_t_2[0] = 6;\n",
       "  __pyx_t_2[1] = 7;\n",
       "  __pyx_t_2[2] = 8;\n",
       "  __pyx_t_2[3] = 9;\n",
       "  __pyx_t_2[4] = 10;\n",
       "  memcpy(&(__pyx_v_b[5]), __pyx_t_2, sizeof(__pyx_v_b[0]) * (5));\n",
       "
 06: 
\n", "
+07:     for i in b[:3]:
\n", "
  __pyx_t_4 = (__pyx_v_b + 3);\n",
       "  for (__pyx_t_5 = __pyx_v_b; __pyx_t_5 < __pyx_t_4; __pyx_t_5++) {\n",
       "    __pyx_t_3 = __pyx_t_5;\n",
       "    __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;}\n",
       "    __Pyx_GOTREF(__pyx_t_6);\n",
       "    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_6);\n",
       "    __pyx_t_6 = 0;\n",
       "
+08:         print(i+1)
\n", "
    __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;}\n",
       "    __Pyx_GOTREF(__pyx_t_6);\n",
       "    if (__Pyx_PrintOne(0, __pyx_t_6) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
       "  }\n",
       "
 09: 
\n", "
+10:     return b
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_6);\n",
       "  __pyx_r = __pyx_t_6;\n",
       "  __pyx_t_6 = 0;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "def carrays():\n", " cdef int[10] a, b\n", " a[:5] = [1,2,3,4,5]\n", " b = a\n", " b[5:] = [6,7,8,9,10]\n", "\n", " for i in b[:3]:\n", " print(i+1)\n", "\n", " return b" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "3\n", "4\n" ] }, { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "carrays()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# C tuples" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.beta1

\n", "

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

\n", "
 01: 
\n", "
+02: def ctuples():
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples = {\"ctuples\", (PyCFunction)__pyx_pw_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples, METH_NOARGS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_1ctuples(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"ctuples (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_ctuples(__pyx_self);\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e_ctuples(CYTHON_UNUSED PyObject *__pyx_self) {\n",
       "  int __pyx_v_a;\n",
       "  double __pyx_v_b;\n",
       "  __pyx_ctuple_int__and_double __pyx_v_t;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"ctuples\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_2);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_28b17313f2e630a40c1e37e0dbcc1e7e.ctuples\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "/* … */\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+03:     cdef int a = 42
\n", "
  __pyx_v_a = 42;\n",
       "
+04:     cdef double b = a / 5.0
\n", "
  __pyx_v_b = (__pyx_v_a / 5.0);\n",
       "
 05: 
\n", "
+06:     cdef (int, double) t = (a, b)
\n", "
  __pyx_t_1.f0 = __pyx_v_a;\n",
       "  __pyx_t_1.f1 = __pyx_v_b;\n",
       "  __pyx_v_t = __pyx_t_1;\n",
       "
+07:     print(t[0])
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  if (__Pyx_PrintOne(0, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "
+08:     print(t[1])
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  if (__Pyx_PrintOne(0, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "
+09:     print(t)
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  if (__Pyx_PrintOne(0, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "
 10: 
\n", "
+11:     return t
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_r = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "def ctuples():\n", " cdef int a = 42\n", " cdef double b = a / 5.0\n", "\n", " cdef (int, double) t = (a, b)\n", " print(t[0])\n", " print(t[1])\n", " print(t)\n", "\n", " return t\n" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "42\n", "8.4\n", "(42, 8.4)\n" ] }, { "data": { "text/plain": [ "(42, 8.4)" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ctuples()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# C++" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.beta1

\n", "

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

\n", "
+1: # distutils: language=c++
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 2: 
\n", "
 3: 
\n", "
 4: from libcpp.vector cimport vector
\n", "
 5: 
\n", "
+6: def func():
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_1func(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_1func = {\"func\", (PyCFunction)__pyx_pw_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_1func, METH_NOARGS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_1func(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"func (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_func(__pyx_self);\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5_func(CYTHON_UNUSED PyObject *__pyx_self) {\n",
       "  std::vector<int>  __pyx_v_v;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"func\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_1);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_a1e5605f1fdd147ec2c410b3c5d592f5.func\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "/* … */\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 7:     cdef vector[int] v
\n", "
+8:     v.push_back(10)
\n", "
  try {\n",
       "    __pyx_v_v.push_back(10);\n",
       "  } catch(...) {\n",
       "    __Pyx_CppExn2PyErr();\n",
       "    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  }\n",
       "
+9:     return v
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_r = __pyx_t_1;\n",
       "  __pyx_t_1 = 0;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "# distutils: language=c++\n", "\n", "\n", "from libcpp.vector cimport vector\n", "\n", "def func():\n", " cdef vector[int] v\n", " v.push_back(10)\n", " return v\n" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[10]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "func()" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_57278ffaa1a4383a1c5140c04c32e598.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.beta1

\n", "

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

\n", "
+01: # distutils: language=c++
\n", "
  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  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;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 02: 
\n", "
 03: from libcpp.vector cimport vector
\n", "
 04: 
\n", "
 05: cdef class Integers:
\n", "
 06:     cdef vector[int] _values
\n", "
 07: 
\n", "
+08:     def add(self, int value):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_1add(PyObject *__pyx_v_self, PyObject *__pyx_arg_value); /*proto*/\n",
       "static PyObject *__pyx_pw_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_1add(PyObject *__pyx_v_self, PyObject *__pyx_arg_value) {\n",
       "  int __pyx_v_value;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"add (wrapper)\", 0);\n",
       "  assert(__pyx_arg_value); {\n",
       "    __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;}\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_57278ffaa1a4383a1c5140c04c32e598.Integers.add\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __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));\n",
       "  int __pyx_lineno = 0;\n",
       "  const char *__pyx_filename = NULL;\n",
       "  int __pyx_clineno = 0;\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "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) {\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"add\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_r = Py_None; __Pyx_INCREF(Py_None);\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_57278ffaa1a4383a1c5140c04c32e598.Integers.add\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "
+09:         self._values.push_back(value)
\n", "
  try {\n",
       "    __pyx_v_self->_values.push_back(__pyx_v_value);\n",
       "  } catch(...) {\n",
       "    __Pyx_CppExn2PyErr();\n",
       "    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  }\n",
       "
 10: 
\n", "
+11:     def __repr__(self):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_3__repr__(PyObject *__pyx_v_self); /*proto*/\n",
       "static PyObject *__pyx_pw_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_3__repr__(PyObject *__pyx_v_self) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"__repr__ (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_2__repr__(((struct __pyx_obj_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_Integers *)__pyx_v_self));\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_8Integers_2__repr__(struct __pyx_obj_46_cython_magic_57278ffaa1a4383a1c5140c04c32e598_Integers *__pyx_v_self) {\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"__repr__\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_1);\n",
       "  __Pyx_XDECREF(__pyx_t_2);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_57278ffaa1a4383a1c5140c04c32e598.Integers.__repr__\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "
+12:         return repr(self._values)
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __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;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_r = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "# distutils: language=c++\n", "\n", "from libcpp.vector cimport vector\n", "\n", "cdef class Integers:\n", " cdef vector[int] _values\n", "\n", " def add(self, int value):\n", " self._values.push_back(value)\n", "\n", " def __repr__(self):\n", " return repr(self._values)\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[2, 3]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = Integers()\n", "x.add(2)\n", "x.add(3)\n", "x" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.0b3+" } }, "nbformat": 4, "nbformat_minor": 0 }