from __future__ import division
import os
import sys
import glob
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline
%precision 4
plt.style.use('ggplot')
import bitey
%load_ext cythonmagic

Using C code in Python

Example: The Fibonacci Sequence

%%file c_fib.h
double c_fib(int n);
Overwriting c_fib.h
%%file c_fib.c
double c_fib(int n) {
    double tmp, a = 0, b = 1;
    for (int i=0; i<n; i++) {
        tmp = a;
        a = a + b;
        b = tmp;
    }
    return a;
}
Overwriting c_fib.c

Using clang and bitey

!clang -O3 -emit-llvm -c c_fib.c -o bitey_fib.o
import bitey_fib
bitey_fib.c_fib(10)
55.0000

Using gcc and ctypes

! gcc -O3 -bundle -undefined dynamic_lookup c_fib.c -o ctypes_fib.so
# For Unix systmes
# ! gcc -O3 -fPIC -shared -std=c99  c_fib.c -o ctypes_fib.so
from ctypes import CDLL, c_int, c_double

def ctypes_fib(n):

    # Use ctypes to load the library
    lib = CDLL('./ctypes_fib.so')

    # We need to give the argument and return types explicitly
    lib.c_fib.argtypes = [c_int]
    lib.c_fib.restype  = c_double

    return lib.c_fib(n)
ctypes_fib(10)
55.0000

Using Cython

%load_ext cythonmagic
The cythonmagic extension is already loaded. To reload it, use:
  %reload_ext cythonmagic
%%file cy_fib.pxd
cdef extern from "c_fib.h":
    double c_fib(int n)
Overwriting cy_fib.pxd
%%file cy_fib.pyx
cimport cy_fib

cpdef cython_fib(n):
    return cy_fib.c_fib(n)
Overwriting cy_fib.pyx
%%file setup.py
from distutils.core import setup, Extension
from Cython.Build import cythonize

ext = Extension("cy_fib",
              sources=["cy_fib.pyx", "c_fib.c"])

setup(name = "cython_fib",
      ext_modules = cythonize(ext))
Overwriting setup.py
! python setup.py build_ext -i &> /dev/null

Benchmark

import cy_fib
import bitey_fib
print ctypes_fib(100)
print bitey_fib.c_fib(100)
print cy_fib.cython_fib(100)
3.54224848179e+20
3.54224848179e+20
3.54224848179e+20
%timeit -n 1000 ctypes_fib(100)
%timeit -n 1000 bitey_fib.c_fib(100)
%timeit -n 1000 cy_fib.cython_fib(100)
1000 loops, best of 3: 92.3 µs per loop
1000 loops, best of 3: 905 ns per loop
1000 loops, best of 3: 264 ns per loop