Commit b67e5567 authored by Stefan Behnel's avatar Stefan Behnel

Fix line endings.

parent e6a49ace
This example directory is organized like the ``Cython/docs/src/`` directory, This example directory is organized like the ``Cython/docs/src/`` directory,
with one directory per ``.rst`` file. All files in this directory are tested with one directory per ``.rst`` file. All files in this directory are tested
in the :file:`runtests.py` with the mode `compile`. in the :file:`runtests.py` with the mode `compile`.
def say_hello_to(name): def say_hello_to(name):
print("Hello %s!" % name) print("Hello %s!" % name)
from distutils.core import setup from distutils.core import setup
from Cython.Build import cythonize from Cython.Build import cythonize
setup(name='Hello world app', setup(name='Hello world app',
ext_modules=cythonize("hello.pyx")) ext_modules=cythonize("hello.pyx"))
cdef double f(double x) except? -2: cdef double f(double x) except? -2:
return x ** 2 - x return x ** 2 - x
def f(x): def f(x):
return x ** 2 - x return x ** 2 - x
def integrate_f(a, b, N): def integrate_f(a, b, N):
s = 0 s = 0
dx = (b - a) / N dx = (b - a) / N
for i in range(N): for i in range(N):
s += f(a + i * dx) s += f(a + i * dx)
return s * dx return s * dx
def f(double x): def f(double x):
return x ** 2 - x return x ** 2 - x
def integrate_f(double a, double b, int N): def integrate_f(double a, double b, int N):
cdef int i cdef int i
cdef double s, dx cdef double s, dx
s = 0 s = 0
dx = (b - a) / N dx = (b - a) / N
for i in range(N): for i in range(N):
s += f(a + i * dx) s += f(a + i * dx)
return s * dx return s * dx
from cpython cimport array from cpython cimport array
import array import array
cdef array.array int_array_template = array.array('i', []) cdef array.array int_array_template = array.array('i', [])
cdef array.array newarray cdef array.array newarray
# create an array with 3 elements with same type as template # create an array with 3 elements with same type as template
newarray = array.clone(int_array_template, 3, zero=False) newarray = array.clone(int_array_template, 3, zero=False)
from cpython cimport array from cpython cimport array
import array import array
cdef array.array a = array.array('i', [1, 2, 3]) cdef array.array a = array.array('i', [1, 2, 3])
cdef int[:] ca = a cdef int[:] ca = a
cdef int overhead(object a): cdef int overhead(object a):
cdef int[:] ca = a cdef int[:] ca = a
return ca[0] return ca[0]
cdef int no_overhead(int[:] ca): cdef int no_overhead(int[:] ca):
return ca[0] return ca[0]
print(overhead(a)) # new memory view will be constructed, overhead print(overhead(a)) # new memory view will be constructed, overhead
print(no_overhead(ca)) # ca is already a memory view, so no overhead print(no_overhead(ca)) # ca is already a memory view, so no overhead
from cpython cimport array from cpython cimport array
import array import array
cdef array.array a = array.array('i', [1, 2, 3]) cdef array.array a = array.array('i', [1, 2, 3])
cdef array.array b = array.array('i', [4, 5, 6]) cdef array.array b = array.array('i', [4, 5, 6])
# extend a with b, resize as needed # extend a with b, resize as needed
array.extend(a, b) array.extend(a, b)
# resize a, leaving just original three elements # resize a, leaving just original three elements
array.resize(a, len(a) - len(b)) array.resize(a, len(a) - len(b))
from cpython cimport array from cpython cimport array
import array import array
cdef array.array a = array.array('i', [1, 2, 3]) cdef array.array a = array.array('i', [1, 2, 3])
cdef int[:] ca = a cdef int[:] ca = a
print(ca[0]) print(ca[0])
from cpython cimport array from cpython cimport array
import array import array
cdef array.array a = array.array('i', [1, 2, 3]) cdef array.array a = array.array('i', [1, 2, 3])
# access underlying pointer: # access underlying pointer:
print(a.data.as_ints[0]) print(a.data.as_ints[0])
from libc.string cimport memset from libc.string cimport memset
memset(a.data.as_voidptr, 0, len(a) * sizeof(int)) memset(a.data.as_voidptr, 0, len(a) * sizeof(int))
from sin_of_square cimport Function, SinOfSquareFunction from sin_of_square cimport Function, SinOfSquareFunction
def integrate(Function f, double a, double b, int N): def integrate(Function f, double a, double b, int N):
cdef int i cdef int i
cdef double s, dx cdef double s, dx
if f is None: if f is None:
raise ValueError("f cannot be None") raise ValueError("f cannot be None")
s = 0 s = 0
dx = (b - a) / N dx = (b - a) / N
for i in range(N): for i in range(N):
s += f.evaluate(a + i * dx) s += f.evaluate(a + i * dx)
return s * dx return s * dx
print(integrate(SinOfSquareFunction(), 0, 1, 10000)) print(integrate(SinOfSquareFunction(), 0, 1, 10000))
class MathFunction(object): class MathFunction(object):
def __init__(self, name, operator): def __init__(self, name, operator):
self.name = name self.name = name
self.operator = operator self.operator = operator
def __call__(self, *operands): def __call__(self, *operands):
return self.operator(*operands) return self.operator(*operands)
cdef class Function: cdef class Function:
cpdef double evaluate(self, double x) except *: cpdef double evaluate(self, double x) except *:
return 0 return 0
# cython: nonecheck=True # cython: nonecheck=True
# ^^^ Turns on nonecheck globally # ^^^ Turns on nonecheck globally
import cython import cython
cdef class MyClass: cdef class MyClass:
pass pass
# Turn off nonecheck locally for the function # Turn off nonecheck locally for the function
@cython.nonecheck(False) @cython.nonecheck(False)
def func(): def func():
cdef MyClass obj = None cdef MyClass obj = None
try: try:
# Turn nonecheck on again for a block # Turn nonecheck on again for a block
with cython.nonecheck(True): with cython.nonecheck(True):
print(obj.myfunc()) # Raises exception print(obj.myfunc()) # Raises exception
except AttributeError: except AttributeError:
pass pass
print(obj.myfunc()) # Hope for a crash! print(obj.myfunc()) # Hope for a crash!
from libc.math cimport sin from libc.math cimport sin
cdef class Function: cdef class Function:
cpdef double evaluate(self, double x) except *: cpdef double evaluate(self, double x) except *:
return 0 return 0
cdef class SinOfSquareFunction(Function): cdef class SinOfSquareFunction(Function):
cpdef double evaluate(self, double x) except *: cpdef double evaluate(self, double x) except *:
return sin(x ** 2) return sin(x ** 2)
from sin_of_square cimport Function from sin_of_square cimport Function
cdef class WaveFunction(Function): cdef class WaveFunction(Function):
# Not available in Python-space: # Not available in Python-space:
cdef double offset cdef double offset
# Available in Python-space: # Available in Python-space:
cdef public double freq cdef public double freq
# Available in Python-space, but only for reading: # Available in Python-space, but only for reading:
cdef readonly double scale cdef readonly double scale
# Available in Python-space: # Available in Python-space:
@property @property
def period(self): def period(self):
return 1.0 / self.freq return 1.0 / self.freq
@period.setter @period.setter
def period(self, value): def period(self, value):
self.freq = 1.0 / value self.freq = 1.0 / value
# queue.pyx # queue.pyx
cimport cqueue cimport cqueue
cdef class Queue: cdef class Queue:
cdef cqueue.Queue* _c_queue cdef cqueue.Queue* _c_queue
def __cinit__(self): def __cinit__(self):
self._c_queue = cqueue.queue_new() self._c_queue = cqueue.queue_new()
# queue.pyx # queue.pyx
cimport cqueue cimport cqueue
cdef class Queue: cdef class Queue:
cdef cqueue.Queue* _c_queue cdef cqueue.Queue* _c_queue
def __cinit__(self): def __cinit__(self):
self._c_queue = cqueue.queue_new() self._c_queue = cqueue.queue_new()
if self._c_queue is NULL: if self._c_queue is NULL:
raise MemoryError() raise MemoryError()
from __future__ import print_function from __future__ import print_function
import time import time
import queue import queue
Q = queue.Queue() Q = queue.Queue()
Q.append(10) Q.append(10)
Q.append(20) Q.append(20)
print(Q.peek()) print(Q.peek())
print(Q.pop()) print(Q.pop())
print(Q.pop()) print(Q.pop())
try: try:
print(Q.pop()) print(Q.pop())
except IndexError as e: except IndexError as e:
print("Error message:", e) # Prints "Queue is empty" print("Error message:", e) # Prints "Queue is empty"
i = 10000 i = 10000
values = range(i) values = range(i)
start_time = time.time() start_time = time.time()
Q.extend(values) Q.extend(values)
end_time = time.time() - start_time end_time = time.time() - start_time
print("Adding {} items took {:1.3f} msecs.".format(i, 1000 * end_time)) print("Adding {} items took {:1.3f} msecs.".format(i, 1000 * end_time))
for i in range(41): for i in range(41):
Q.pop() Q.pop()
Q.pop() Q.pop()
print("The answer is:") print("The answer is:")
print(Q.pop()) print(Q.pop())
# distutils: language=c++ # distutils: language=c++
from libcpp.vector cimport vector from libcpp.vector cimport vector
def primes(unsigned int nb_primes): def primes(unsigned int nb_primes):
cdef int n, i cdef int n, i
cdef vector[int] p cdef vector[int] p
p.reserve(nb_primes) # allocate memory for 'nb_primes' elements. p.reserve(nb_primes) # allocate memory for 'nb_primes' elements.
n = 2 n = 2
while p.size() < nb_primes: # size() for vectors is similar to len() while p.size() < nb_primes: # size() for vectors is similar to len()
for i in p: for i in p:
if n % i == 0: if n % i == 0:
break break
else: else:
p.push_back(n) # push_back is similar to append() p.push_back(n) # push_back is similar to append()
n += 1 n += 1
# Vectors are automatically converted to Python # Vectors are automatically converted to Python
# lists when converted to Python objects. # lists when converted to Python objects.
return p return p
from libc.stdlib cimport atoi from libc.stdlib cimport atoi
cdef parse_charptr_to_py_int(char* s): cdef parse_charptr_to_py_int(char* s):
assert s is not NULL, "byte string value is NULL" assert s is not NULL, "byte string value is NULL"
return atoi(s) # note: atoi() has no error detection! return atoi(s) # note: atoi() has no error detection!
""" """
>>> sin(0) >>> sin(0)
0.0 0.0
""" """
cdef extern from "math.h": cdef extern from "math.h":
cpdef double sin(double x) cpdef double sin(double x)
cdef extern from "string.h": cdef extern from "string.h":
char* strstr(const char *haystack, const char *needle) char* strstr(const char *haystack, const char *needle)
cdef extern from "string.h": cdef extern from "string.h":
char* strstr(const char *haystack, const char *needle) char* strstr(const char *haystack, const char *needle)
cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh"
cdef char* pos = strstr(needle='akd', haystack=data) cdef char* pos = strstr(needle='akd', haystack=data)
print(pos is not NULL) print(pos is not NULL)
from libc.math cimport sin from libc.math cimport sin
cdef double f(double x): cdef double f(double x):
return sin(x * x) return sin(x * x)
from cpython.version cimport PY_VERSION_HEX from cpython.version cimport PY_VERSION_HEX
# Python version >= 3.2 final ? # Python version >= 3.2 final ?
print(PY_VERSION_HEX >= 0x030200F0) print(PY_VERSION_HEX >= 0x030200F0)
from distutils.core import setup from distutils.core import setup
from distutils.extension import Extension from distutils.extension import Extension
from Cython.Build import cythonize from Cython.Build import cythonize
ext_modules = [ ext_modules = [
Extension("demo", Extension("demo",
sources=["demo.pyx"], sources=["demo.pyx"],
libraries=["m"] # Unix-like specific libraries=["m"] # Unix-like specific
) )
] ]
setup(name="Demos", setup(name="Demos",
ext_modules=cythonize(ext_modules)) ext_modules=cythonize(ext_modules))
import random import random
from libc.stdlib cimport malloc, free from libc.stdlib cimport malloc, free
def random_noise(int number=1): def random_noise(int number=1):
cdef int i cdef int i
# allocate number * sizeof(double) bytes of memory # allocate number * sizeof(double) bytes of memory
cdef double *my_array = <double *> malloc(number * sizeof(double)) cdef double *my_array = <double *> malloc(number * sizeof(double))
if not my_array: if not my_array:
raise MemoryError() raise MemoryError()
try: try:
ran = random.normalvariate ran = random.normalvariate
for i in range(number): for i in range(number):
my_array[i] = ran(0, 1) my_array[i] = ran(0, 1)
# ... let's just assume we do some more heavy C calculations here to make up # ... let's just assume we do some more heavy C calculations here to make up
# for the work that it takes to pack the C double values into Python float # for the work that it takes to pack the C double values into Python float
# objects below, right after throwing away the existing objects above. # objects below, right after throwing away the existing objects above.
return [x for x in my_array[:number]] return [x for x in my_array[:number]]
finally: finally:
# return the previously allocated memory to the system # return the previously allocated memory to the system
free(my_array) free(my_array)
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
cdef class SomeMemory: cdef class SomeMemory:
cdef double* data cdef double* data
def __cinit__(self, size_t number): def __cinit__(self, size_t number):
# allocate some memory (uninitialised, may contain arbitrary data) # allocate some memory (uninitialised, may contain arbitrary data)
self.data = <double*> PyMem_Malloc(number * sizeof(double)) self.data = <double*> PyMem_Malloc(number * sizeof(double))
if not self.data: if not self.data:
raise MemoryError() raise MemoryError()
def resize(self, size_t new_number): def resize(self, size_t new_number):
# Allocates new_number * sizeof(double) bytes, # Allocates new_number * sizeof(double) bytes,
# preserving the current content and making a best-effort to # preserving the current content and making a best-effort to
# re-use the original data location. # re-use the original data location.
mem = <double*> PyMem_Realloc(self.data, new_number * sizeof(double)) mem = <double*> PyMem_Realloc(self.data, new_number * sizeof(double))
if not mem: if not mem:
raise MemoryError() raise MemoryError()
# Only overwrite the pointer if the memory was really reallocated. # Only overwrite the pointer if the memory was really reallocated.
# On error (mem is NULL), the originally memory has not been freed. # On error (mem is NULL), the originally memory has not been freed.
self.data = mem self.data = mem
def __dealloc__(self): def __dealloc__(self):
PyMem_Free(self.data) # no-op if self.data is NULL PyMem_Free(self.data) # no-op if self.data is NULL
import numpy as np import numpy as np
def naive_convolve(f, g): def naive_convolve(f, g):
# f is an image and is indexed by (v, w) # f is an image and is indexed by (v, w)
# g is a filter kernel and is indexed by (s, t), # g is a filter kernel and is indexed by (s, t),
# it needs odd dimensions # it needs odd dimensions
# h is the output image and is indexed by (x, y), # h is the output image and is indexed by (x, y),
# it is not cropped # it is not cropped
if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1: if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
raise ValueError("Only odd dimensions on filter supported") raise ValueError("Only odd dimensions on filter supported")
# smid and tmid are number of pixels between the center pixel # smid and tmid are number of pixels between the center pixel
# and the edge, ie for a 5x5 filter they will be 2. # and the edge, ie for a 5x5 filter they will be 2.
# #
# The output size is calculated by adding smid, tmid to each # The output size is calculated by adding smid, tmid to each
# side of the dimensions of the input image. # side of the dimensions of the input image.
vmax = f.shape[0] vmax = f.shape[0]
wmax = f.shape[1] wmax = f.shape[1]
smax = g.shape[0] smax = g.shape[0]
tmax = g.shape[1] tmax = g.shape[1]
smid = smax // 2 smid = smax // 2
tmid = tmax // 2 tmid = tmax // 2
xmax = vmax + 2 * smid xmax = vmax + 2 * smid
ymax = wmax + 2 * tmid ymax = wmax + 2 * tmid
# Allocate result image. # Allocate result image.
h = np.zeros([xmax, ymax], dtype=f.dtype) h = np.zeros([xmax, ymax], dtype=f.dtype)
# Do convolution # Do convolution
for x in range(xmax): for x in range(xmax):
for y in range(ymax): for y in range(ymax):
# Calculate pixel value for h at (x,y). Sum one component # Calculate pixel value for h at (x,y). Sum one component
# for each pixel (s, t) of the filter g. # for each pixel (s, t) of the filter g.
s_from = max(smid - x, -smid) s_from = max(smid - x, -smid)
s_to = min((xmax - x) - smid, smid + 1) s_to = min((xmax - x) - smid, smid + 1)
t_from = max(tmid - y, -tmid) t_from = max(tmid - y, -tmid)
t_to = min((ymax - y) - tmid, tmid + 1) t_to = min((ymax - y) - tmid, tmid + 1)
value = 0 value = 0
for s in range(s_from, s_to): for s in range(s_from, s_to):
for t in range(t_from, t_to): for t in range(t_from, t_to):
v = x - smid + s v = x - smid + s
w = y - tmid + t w = y - tmid + t
value += g[smid - s, tmid - t] * f[v, w] value += g[smid - s, tmid - t] * f[v, w]
h[x, y] = value h[x, y] = value
return h return h
# calc_pi.py # calc_pi.py
def recip_square(i): def recip_square(i):
return 1. / i ** 2 return 1. / i ** 2
def approx_pi(n=10000000): def approx_pi(n=10000000):
val = 0. val = 0.
for k in range(1, n + 1): for k in range(1, n + 1):
val += recip_square(k) val += recip_square(k)
return (6 * val) ** .5 return (6 * val) ** .5
# cython: profile=True # cython: profile=True
# calc_pi.pyx # calc_pi.pyx
def recip_square(int i): def recip_square(int i):
return 1. / i ** 2 return 1. / i ** 2
def approx_pi(int n=10000000): def approx_pi(int n=10000000):
cdef double val = 0. cdef double val = 0.
cdef int k cdef int k
for k in range(1, n + 1): for k in range(1, n + 1):
val += recip_square(k) val += recip_square(k)
return (6 * val) ** .5 return (6 * val) ** .5
# cython: profile=True # cython: profile=True
# calc_pi.pyx # calc_pi.pyx
cdef inline double recip_square(int i): cdef inline double recip_square(int i):
return 1. / (i * i) return 1. / (i * i)
def approx_pi(int n=10000000): def approx_pi(int n=10000000):
cdef double val = 0. cdef double val = 0.
cdef int k cdef int k
for k in range(1, n + 1): for k in range(1, n + 1):
val += recip_square(k) val += recip_square(k)
return (6 * val) ** .5 return (6 * val) ** .5
# cython: profile=True # cython: profile=True
# calc_pi.pyx # calc_pi.pyx
cimport cython cimport cython
@cython.profile(False) @cython.profile(False)
cdef inline double recip_square(int i): cdef inline double recip_square(int i):
return 1. / (i * i) return 1. / (i * i)
def approx_pi(int n=10000000): def approx_pi(int n=10000000):
cdef double val = 0. cdef double val = 0.
cdef int k cdef int k
for k in range(1, n + 1): for k in range(1, n + 1):
val += recip_square(k) val += recip_square(k)
return (6 * val) ** .5 return (6 * val) ** .5
cimport cython cimport cython
@cython.profile(False) @cython.profile(False)
def my_often_called_function(): def my_often_called_function():
pass pass
# profile.py # profile.py
import pstats, cProfile import pstats, cProfile
import calc_pi import calc_pi
cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof") cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof")
s = pstats.Stats("Profile.prof") s = pstats.Stats("Profile.prof")
s.strip_dirs().sort_stats("time").print_stats() s.strip_dirs().sort_stats("time").print_stats()
# profile.py # profile.py
import pstats, cProfile import pstats, cProfile
import pyximport import pyximport
pyximport.install() pyximport.install()
import calc_pi import calc_pi
cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof") cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof")
s = pstats.Stats("Profile.prof") s = pstats.Stats("Profile.prof")
s.strip_dirs().sort_stats("time").print_stats() s.strip_dirs().sort_stats("time").print_stats()
def myfunction(x, y=2): def myfunction(x, y=2):
a = x - y a = x - y
return a + x * y return a + x * y
def _helper(a): def _helper(a):
return a + 1 return a + 1
class A: class A:
def __init__(self, b=0): def __init__(self, b=0):
self.a = 3 self.a = 3
self.b = b self.b = b
def foo(self, x): def foo(self, x):
print(x + _helper(1.0)) print(x + _helper(1.0))
cpdef int myfunction(int x, int y=2): cpdef int myfunction(int x, int y=2):
a = x - y a = x - y
return a + x * y return a + x * y
cdef double _helper(double a): cdef double _helper(double a):
return a + 1 return a + 1
cdef class A: cdef class A:
cdef public int a, b cdef public int a, b
def __init__(self, b=0): def __init__(self, b=0):
self.a = 3 self.a = 3
self.b = b self.b = b
cpdef foo(self, double x): cpdef foo(self, double x):
print(x + _helper(1.0)) print(x + _helper(1.0))
import cython import cython
def func(foo: dict, bar: cython.int) -> tuple: def func(foo: dict, bar: cython.int) -> tuple:
foo["hello world"] = 3 + bar foo["hello world"] = 3 + bar
return foo, 5 return foo, 5
import cython import cython
@cython.locals(counts=cython.int[10], digit=cython.int) @cython.locals(counts=cython.int[10], digit=cython.int)
def count_digits(digits): def count_digits(digits):
""" """
>>> digits = '01112222333334445667788899' >>> digits = '01112222333334445667788899'
>>> count_digits(map(int, digits)) >>> count_digits(map(int, digits))
[1, 3, 4, 5, 3, 1, 2, 2, 3, 2] [1, 3, 4, 5, 3, 1, 2, 2, 3, 2]
""" """
counts = [0] * 10 counts = [0] * 10
for digit in digits: for digit in digits:
assert 0 <= digit <= 9 assert 0 <= digit <= 9
counts[digit] += 1 counts[digit] += 1
return counts return counts
import cython import cython
@cython.cclass @cython.cclass
class A: class A:
cython.declare(a=cython.int, b=cython.int) cython.declare(a=cython.int, b=cython.int)
c = cython.declare(cython.int, visibility='public') c = cython.declare(cython.int, visibility='public')
d = cython.declare(cython.int) # private by default. d = cython.declare(cython.int) # private by default.
e = cython.declare(cython.int, visibility='readonly') e = cython.declare(cython.int, visibility='readonly')
def __init__(self, a, b, c, d=5, e=3): def __init__(self, a, b, c, d=5, e=3):
self.a = a self.a = a
self.b = b self.b = b
self.c = c self.c = c
self.d = d self.d = d
self.e = e self.e = e
import cython import cython
if cython.compiled: if cython.compiled:
print("Yep, I'm compiled.") print("Yep, I'm compiled.")
else: else:
print("Just a lowly interpreted script.") print("Just a lowly interpreted script.")
import cython import cython
x = cython.declare(cython.int) # cdef int x x = cython.declare(cython.int) # cdef int x
y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721 y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721
import cython import cython
cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y
def dostuff(n): def dostuff(n):
t = 0 t = 0
for i in range(n): for i in range(n):
t += i t += i
return t return t
import cython import cython
@cython.exceptval(-1) @cython.exceptval(-1)
def func(x: cython.int) -> cython.int: def func(x: cython.int) -> cython.int:
if x < 0: if x < 0:
raise ValueError("need integer >= 0") raise ValueError("need integer >= 0")
return x + 1 return x + 1
import cython import cython
@cython.locals(a=cython.long, b=cython.long, n=cython.longlong) @cython.locals(a=cython.long, b=cython.long, n=cython.longlong)
def foo(a, b, x, y): def foo(a, b, x, y):
n = a * b n = a * b
# ... # ...
# mymodule.py # mymodule.py
import cython import cython
# override with Python import if not in compiled code # override with Python import if not in compiled code
if not cython.compiled: if not cython.compiled:
from math import sin from math import sin
# calls sin() from math.h when compiled with Cython and math.sin() in Python # calls sin() from math.h when compiled with Cython and math.sin() in Python
print(sin(0)) print(sin(0))
import cython import cython
def func(): def func():
# Cython types are evaluated as for cdef declarations # Cython types are evaluated as for cdef declarations
x: cython.int # cdef int x x: cython.int # cdef int x
y: cython.double = 0.57721 # cdef double y = 0.57721 y: cython.double = 0.57721 # cdef double y = 0.57721
z: cython.float = 0.57721 # cdef float z = 0.57721 z: cython.float = 0.57721 # cdef float z = 0.57721
# Python types shadow Cython types for compatibility reasons # Python types shadow Cython types for compatibility reasons
a: float = 0.54321 # cdef double a = 0.54321 a: float = 0.54321 # cdef double a = 0.54321
b: int = 5 # cdef object b = 5 b: int = 5 # cdef object b = 5
c: long = 6 # cdef object c = 6 c: long = 6 # cdef object c = 6
pass pass
@cython.cclass @cython.cclass
class A: class A:
a: cython.int a: cython.int
b: cython.int b: cython.int
def __init__(self, b=0): def __init__(self, b=0):
self.a = 3 self.a = 3
self.b = b self.b = b
from to_unicode cimport _text from to_unicode cimport _text
def api_func(s): def api_func(s):
text_input = _text(s) text_input = _text(s)
# ... # ...
def process_byte_data(unsigned char[:] data): def process_byte_data(unsigned char[:] data):
length = data.shape[0] length = data.shape[0]
first_byte = data[0] first_byte = data[0]
slice_view = data[1:-1] slice_view = data[1:-1]
# ... # ...
# cython: c_string_type=unicode, c_string_encoding=utf8 # cython: c_string_type=unicode, c_string_encoding=utf8
cdef char* c_string = 'abcdefg' cdef char* c_string = 'abcdefg'
# implicit decoding: # implicit decoding:
cdef object py_unicode_object = c_string cdef object py_unicode_object = c_string
# explicit conversion to Python bytes: # explicit conversion to Python bytes:
py_bytes_object = <bytes>c_string py_bytes_object = <bytes>c_string
# cython: c_string_type=str, c_string_encoding=ascii # cython: c_string_type=str, c_string_encoding=ascii
cdef char* c_string = 'abcdefg' cdef char* c_string = 'abcdefg'
# implicit decoding in Py3, bytes conversion in Py2: # implicit decoding in Py3, bytes conversion in Py2:
cdef object py_str_object = c_string cdef object py_str_object = c_string
# explicit conversion to Python bytes: # explicit conversion to Python bytes:
py_bytes_object = <bytes>c_string py_bytes_object = <bytes>c_string
# explicit conversion to Python unicode: # explicit conversion to Python unicode:
py_bytes_object = <unicode>c_string py_bytes_object = <unicode>c_string
# cython: c_string_type=unicode, c_string_encoding=ascii # cython: c_string_type=unicode, c_string_encoding=ascii
def func(): def func():
ustring = u'abc' ustring = u'abc'
cdef char* s = ustring cdef char* s = ustring
return s[0] # returns u'a' return s[0] # returns u'a'
from libc.stdlib cimport malloc from libc.stdlib cimport malloc
from libc.string cimport strcpy, strlen from libc.string cimport strcpy, strlen
cdef char* hello_world = 'hello world' cdef char* hello_world = 'hello world'
cdef Py_ssize_t n = strlen(hello_world) cdef Py_ssize_t n = strlen(hello_world)
cdef char* c_call_returning_a_c_string(): cdef char* c_call_returning_a_c_string():
cdef char* c_string = <char *> malloc((n + 1) * sizeof(char)) cdef char* c_string = <char *> malloc((n + 1) * sizeof(char))
if not c_string: if not c_string:
raise MemoryError() raise MemoryError()
strcpy(c_string, hello_world) strcpy(c_string, hello_world)
return c_string return c_string
cdef void get_a_c_string(char** c_string_ptr, Py_ssize_t *length): cdef void get_a_c_string(char** c_string_ptr, Py_ssize_t *length):
c_string_ptr[0] = <char *> malloc((n + 1) * sizeof(char)) c_string_ptr[0] = <char *> malloc((n + 1) * sizeof(char))
if not c_string_ptr[0]: if not c_string_ptr[0]:
raise MemoryError() raise MemoryError()
strcpy(c_string_ptr[0], hello_world) strcpy(c_string_ptr[0], hello_world)
length[0] = n length[0] = n
cdef extern from "someheader.h": cdef extern from "someheader.h":
ctypedef const char specialChar ctypedef const char specialChar
int process_string(const char* s) int process_string(const char* s)
const unsigned char* look_up_cached_string(const unsigned char* key) const unsigned char* look_up_cached_string(const unsigned char* key)
# distutils: language = c++ # distutils: language = c++
from libcpp.string cimport string from libcpp.string cimport string
def get_bytes(): def get_bytes():
py_bytes_object = b'hello world' py_bytes_object = b'hello world'
cdef string s = py_bytes_object cdef string s = py_bytes_object
s.append('abc') s.append('abc')
py_bytes_object = s py_bytes_object = s
return py_bytes_object return py_bytes_object
from c_func cimport get_a_c_string from c_func cimport get_a_c_string
cdef char* c_string = NULL cdef char* c_string = NULL
cdef Py_ssize_t length = 0 cdef Py_ssize_t length = 0
# get pointer and length from a C function # get pointer and length from a C function
get_a_c_string(&c_string, &length) get_a_c_string(&c_string, &length)
ustring = c_string[:length].decode('UTF-8') ustring = c_string[:length].decode('UTF-8')
# distutils: language = c++ # distutils: language = c++
from libcpp.string cimport string from libcpp.string cimport string
def get_ustrings(): def get_ustrings():
cdef string s = string(b'abcdefg') cdef string s = string(b'abcdefg')
ustring1 = s.decode('UTF-8') ustring1 = s.decode('UTF-8')
ustring2 = s[2:-2].decode('UTF-8') ustring2 = s[2:-2].decode('UTF-8')
return ustring1, ustring2 return ustring1, ustring2
cdef bytes bytes_string = b"hello to A bytes' world" cdef bytes bytes_string = b"hello to A bytes' world"
cdef char c cdef char c
for c in bytes_string: for c in bytes_string:
if c == 'A': if c == 'A':
print("Found the letter A") print("Found the letter A")
cdef char* c_string = "Hello to A C-string's world" cdef char* c_string = "Hello to A C-string's world"
cdef char c cdef char c
for c in c_string[:11]: for c in c_string[:11]:
if c == 'A': if c == 'A':
print("Found the letter A") print("Found the letter A")
cdef unicode ustring = u'Hello world' cdef unicode ustring = u'Hello world'
# NOTE: no typing required for 'uchar' ! # NOTE: no typing required for 'uchar' !
for uchar in ustring: for uchar in ustring:
if uchar == u'A': if uchar == u'A':
print("Found the letter A") print("Found the letter A")
cpdef void is_in(Py_UCS4 uchar_val): cpdef void is_in(Py_UCS4 uchar_val):
if uchar_val in u'abcABCxY': if uchar_val in u'abcABCxY':
print("The character is in the string.") print("The character is in the string.")
else: else:
print("The character is not in the string") print("The character is not in the string")
from c_func cimport c_call_returning_a_c_string from c_func cimport c_call_returning_a_c_string
cdef char* some_c_string = c_call_returning_a_c_string() cdef char* some_c_string = c_call_returning_a_c_string()
ustring = some_c_string.decode('UTF-8') ustring = some_c_string.decode('UTF-8')
def process_byte_data(unsigned char[:] data): def process_byte_data(unsigned char[:] data):
# ... process the data, here, dummy processing. # ... process the data, here, dummy processing.
cdef bint return_all = (data[0] == 108) cdef bint return_all = (data[0] == 108)
if return_all: if return_all:
return bytes(data) return bytes(data)
else: else:
# example for returning a slice # example for returning a slice
return bytes(data[5:7]) return bytes(data[5:7])
from libc.stdlib cimport free from libc.stdlib cimport free
from c_func cimport get_a_c_string from c_func cimport get_a_c_string
def main(): def main():
cdef char* c_string = NULL cdef char* c_string = NULL
cdef Py_ssize_t length = 0 cdef Py_ssize_t length = 0
# get pointer and length from a C function # get pointer and length from a C function
get_a_c_string(&c_string, &length) get_a_c_string(&c_string, &length)
try: try:
py_bytes_string = c_string[:length] # Performs a copy of the data py_bytes_string = c_string[:length] # Performs a copy of the data
finally: finally:
free(c_string) free(c_string)
# define a global name for whatever char type is used in the module # define a global name for whatever char type is used in the module
ctypedef unsigned char char_type ctypedef unsigned char char_type
cdef char_type[:] _chars(s): cdef char_type[:] _chars(s):
if isinstance(s, unicode): if isinstance(s, unicode):
# encode to the specific encoding used inside of the module # encode to the specific encoding used inside of the module
s = (<unicode>s).encode('utf8') s = (<unicode>s).encode('utf8')
return s return s
# to_unicode.pyx # to_unicode.pyx
from cpython.version cimport PY_MAJOR_VERSION from cpython.version cimport PY_MAJOR_VERSION
cdef unicode _text(s): cdef unicode _text(s):
if type(s) is unicode: if type(s) is unicode:
# Fast path for most common case(s). # Fast path for most common case(s).
return <unicode>s return <unicode>s
elif PY_MAJOR_VERSION < 3 and isinstance(s, bytes): elif PY_MAJOR_VERSION < 3 and isinstance(s, bytes):
# Only accept byte strings as text input in Python 2.x, not in Py3. # Only accept byte strings as text input in Python 2.x, not in Py3.
return (<bytes>s).decode('ascii') return (<bytes>s).decode('ascii')
elif isinstance(s, unicode): elif isinstance(s, unicode):
# We know from the fast path above that 's' can only be a subtype here. # We know from the fast path above that 's' can only be a subtype here.
# An evil cast to <unicode> might still work in some(!) cases, # An evil cast to <unicode> might still work in some(!) cases,
# depending on what the further processing does. To be safe, # depending on what the further processing does. To be safe,
# we can always create a copy instead. # we can always create a copy instead.
return unicode(s) return unicode(s)
else: else:
raise TypeError("Could not convert to unicode.") raise TypeError("Could not convert to unicode.")
from libc.stdlib cimport free from libc.stdlib cimport free
from c_func cimport c_call_returning_a_c_string from c_func cimport c_call_returning_a_c_string
cdef bytes py_string cdef bytes py_string
cdef char* c_string = c_call_returning_a_c_string() cdef char* c_string = c_call_returning_a_c_string()
try: try:
py_string = c_string py_string = c_string
finally: finally:
free(c_string) free(c_string)
from libc.stdlib cimport free from libc.stdlib cimport free
cdef unicode tounicode(char* s): cdef unicode tounicode(char* s):
return s.decode('UTF-8', 'strict') return s.decode('UTF-8', 'strict')
cdef unicode tounicode_with_length( cdef unicode tounicode_with_length(
char* s, size_t length): char* s, size_t length):
return s[:length].decode('UTF-8', 'strict') return s[:length].decode('UTF-8', 'strict')
cdef unicode tounicode_with_length_and_free( cdef unicode tounicode_with_length_and_free(
char* s, size_t length): char* s, size_t length):
try: try:
return s[:length].decode('UTF-8', 'strict') return s[:length].decode('UTF-8', 'strict')
finally: finally:
free(s) free(s)
\ No newline at end of file
# distutils: language = c++ # distutils: language = c++
# matrix.pyx # matrix.pyx
from libcpp.vector cimport vector from libcpp.vector cimport vector
cdef class Matrix: cdef class Matrix:
cdef unsigned ncols cdef unsigned ncols
cdef vector[float] v cdef vector[float] v
def __cinit__(self, unsigned ncols): def __cinit__(self, unsigned ncols):
self.ncols = ncols self.ncols = ncols
def add_row(self): def add_row(self):
"""Adds a row, initially zero-filled.""" """Adds a row, initially zero-filled."""
self.v.resize(self.v.size() + self.ncols) self.v.resize(self.v.size() + self.ncols)
# distutils: language = c++ # distutils: language = c++
from cpython cimport Py_buffer from cpython cimport Py_buffer
from libcpp.vector cimport vector from libcpp.vector cimport vector
cdef class Matrix: cdef class Matrix:
cdef Py_ssize_t ncols cdef Py_ssize_t ncols
cdef Py_ssize_t shape[2] cdef Py_ssize_t shape[2]
cdef Py_ssize_t strides[2] cdef Py_ssize_t strides[2]
cdef vector[float] v cdef vector[float] v
def __cinit__(self, Py_ssize_t ncols): def __cinit__(self, Py_ssize_t ncols):
self.ncols = ncols self.ncols = ncols
def add_row(self): def add_row(self):
"""Adds a row, initially zero-filled.""" """Adds a row, initially zero-filled."""
self.v.resize(self.v.size() + self.ncols) self.v.resize(self.v.size() + self.ncols)
def __getbuffer__(self, Py_buffer *buffer, int flags): def __getbuffer__(self, Py_buffer *buffer, int flags):
cdef Py_ssize_t itemsize = sizeof(self.v[0]) cdef Py_ssize_t itemsize = sizeof(self.v[0])
self.shape[0] = self.v.size() / self.ncols self.shape[0] = self.v.size() / self.ncols
self.shape[1] = self.ncols self.shape[1] = self.ncols
# Stride 1 is the distance, in bytes, between two items in a row; # Stride 1 is the distance, in bytes, between two items in a row;
# this is the distance between two adjacent items in the vector. # this is the distance between two adjacent items in the vector.
# Stride 0 is the distance between the first elements of adjacent rows. # Stride 0 is the distance between the first elements of adjacent rows.
self.strides[1] = <Py_ssize_t>( <char *>&(self.v[1]) self.strides[1] = <Py_ssize_t>( <char *>&(self.v[1])
- <char *>&(self.v[0])) - <char *>&(self.v[0]))
self.strides[0] = self.ncols * self.strides[1] self.strides[0] = self.ncols * self.strides[1]
buffer.buf = <char *>&(self.v[0]) buffer.buf = <char *>&(self.v[0])
buffer.format = 'f' # float buffer.format = 'f' # float
buffer.internal = NULL # see References buffer.internal = NULL # see References
buffer.itemsize = itemsize buffer.itemsize = itemsize
buffer.len = self.v.size() * itemsize # product(shape) * itemsize buffer.len = self.v.size() * itemsize # product(shape) * itemsize
buffer.ndim = 2 buffer.ndim = 2
buffer.obj = self buffer.obj = self
buffer.readonly = 0 buffer.readonly = 0
buffer.shape = self.shape buffer.shape = self.shape
buffer.strides = self.strides buffer.strides = self.strides
buffer.suboffsets = NULL # for pointer arrays only buffer.suboffsets = NULL # for pointer arrays only
def __releasebuffer__(self, Py_buffer *buffer): def __releasebuffer__(self, Py_buffer *buffer):
pass pass
# distutils: language = c++ # distutils: language = c++
from cpython cimport Py_buffer from cpython cimport Py_buffer
from libcpp.vector cimport vector from libcpp.vector cimport vector
cdef class Matrix: cdef class Matrix:
cdef int view_count cdef int view_count
cdef Py_ssize_t ncols cdef Py_ssize_t ncols
cdef vector[float] v cdef vector[float] v
# ... # ...
def __cinit__(self, Py_ssize_t ncols): def __cinit__(self, Py_ssize_t ncols):
self.ncols = ncols self.ncols = ncols
self.view_count = 0 self.view_count = 0
def add_row(self): def add_row(self):
if self.view_count > 0: if self.view_count > 0:
raise ValueError("can't add row while being viewed") raise ValueError("can't add row while being viewed")
self.v.resize(self.v.size() + self.ncols) self.v.resize(self.v.size() + self.ncols)
def __getbuffer__(self, Py_buffer *buffer, int flags): def __getbuffer__(self, Py_buffer *buffer, int flags):
# ... as before # ... as before
self.view_count += 1 self.view_count += 1
def __releasebuffer__(self, Py_buffer *buffer): def __releasebuffer__(self, Py_buffer *buffer):
self.view_count -= 1 self.view_count -= 1
\ No newline at end of file
cdef class Rectangle: cdef class Rectangle:
cdef int x0, y0 cdef int x0, y0
cdef int x1, y1 cdef int x1, y1
def __init__(self, int x0, int y0, int x1, int y1): def __init__(self, int x0, int y0, int x1, int y1):
self.x0 = x0 self.x0 = x0
self.y0 = y0 self.y0 = y0
self.x1 = x1 self.x1 = x1
self.y1 = y1 self.y1 = y1
def area(self): def area(self):
area = (self.x1 - self.x0) * (self.y1 - self.y0) area = (self.x1 - self.x0) * (self.y1 - self.y0)
if area < 0: if area < 0:
area = -area area = -area
return area return area
def rectArea(x0, y0, x1, y1): def rectArea(x0, y0, x1, y1):
rect = Rectangle(x0, y0, x1, y1) rect = Rectangle(x0, y0, x1, y1)
return rect.area() return rect.area()
cdef class Rectangle: cdef class Rectangle:
cdef int x0, y0 cdef int x0, y0
cdef int x1, y1 cdef int x1, y1
def __init__(self, int x0, int y0, int x1, int y1): def __init__(self, int x0, int y0, int x1, int y1):
self.x0 = x0 self.x0 = x0
self.y0 = y0 self.y0 = y0
self.x1 = x1 self.x1 = x1
self.y1 = y1 self.y1 = y1
cdef int _area(self): cdef int _area(self):
area = (self.x1 - self.x0) * (self.y1 - self.y0) area = (self.x1 - self.x0) * (self.y1 - self.y0)
if area < 0: if area < 0:
area = -area area = -area
return area return area
def area(self): def area(self):
return self._area() return self._area()
def rectArea(x0, y0, x1, y1): def rectArea(x0, y0, x1, y1):
cdef Rectangle rect = Rectangle(x0, y0, x1, y1) cdef Rectangle rect = Rectangle(x0, y0, x1, y1)
return rect._area() return rect._area()
cdef class Rectangle: cdef class Rectangle:
cdef int x0, y0 cdef int x0, y0
cdef int x1, y1 cdef int x1, y1
def __init__(self, int x0, int y0, int x1, int y1): def __init__(self, int x0, int y0, int x1, int y1):
self.x0 = x0 self.x0 = x0
self.y0 = y0 self.y0 = y0
self.x1 = x1 self.x1 = x1
self.y1 = y1 self.y1 = y1
cpdef int area(self): cpdef int area(self):
area = (self.x1 - self.x0) * (self.y1 - self.y0) area = (self.x1 - self.x0) * (self.y1 - self.y0)
if area < 0: if area < 0:
area = -area area = -area
return area return area
def rectArea(x0, y0, x1, y1): def rectArea(x0, y0, x1, y1):
cdef Rectangle rect = Rectangle(x0, y0, x1, y1) cdef Rectangle rect = Rectangle(x0, y0, x1, y1)
return rect.area() return rect.area()
cdef class Animal: cdef class Animal:
cdef int number_of_legs cdef int number_of_legs
cdef dict __dict__ cdef dict __dict__
def __cinit__(self, int number_of_legs): def __cinit__(self, int number_of_legs):
self.number_of_legs = number_of_legs self.number_of_legs = number_of_legs
dog = Animal(4) dog = Animal(4)
dog.has_tail = True dog.has_tail = True
cdef class Animal: cdef class Animal:
cdef int number_of_legs cdef int number_of_legs
def __cinit__(self, int number_of_legs): def __cinit__(self, int number_of_legs):
self.number_of_legs = number_of_legs self.number_of_legs = number_of_legs
class ExtendableAnimal(Animal): # Note that we use class, not cdef class class ExtendableAnimal(Animal): # Note that we use class, not cdef class
pass pass
dog = ExtendableAnimal(4) dog = ExtendableAnimal(4)
dog.has_tail = True dog.has_tail = True
\ No newline at end of file
from __future__ import print_function from __future__ import print_function
cdef class Shrubbery: cdef class Shrubbery:
def __init__(self, w, h): def __init__(self, w, h):
self.width = w self.width = w
self.height = h self.height = h
def describe(self): def describe(self):
print("This shrubbery is", self.width, print("This shrubbery is", self.width,
"by", self.height, "cubits.") "by", self.height, "cubits.")
cdef class Shrubbery: cdef class Shrubbery:
cdef public int width, height cdef public int width, height
cdef readonly float depth cdef readonly float depth
from __future__ import print_function from __future__ import print_function
cdef class Shrubbery: cdef class Shrubbery:
cdef int width, height cdef int width, height
def __init__(self, w, h): def __init__(self, w, h):
self.width = w self.width = w
self.height = h self.height = h
def describe(self): def describe(self):
print("This shrubbery is", self.width, print("This shrubbery is", self.width,
"by", self.height, "cubits.") "by", self.height, "cubits.")
from my_module cimport Shrubbery from my_module cimport Shrubbery
cdef Shrubbery another_shrubbery(Shrubbery sh1): cdef Shrubbery another_shrubbery(Shrubbery sh1):
cdef Shrubbery sh2 cdef Shrubbery sh2
sh2 = Shrubbery() sh2 = Shrubbery()
sh2.width = sh1.width sh2.width = sh1.width
sh2.height = sh1.height sh2.height = sh1.height
return sh2 return sh2
from my_module cimport Shrubbery from my_module cimport Shrubbery
cdef widen_shrubbery(Shrubbery sh, extra_width): cdef widen_shrubbery(Shrubbery sh, extra_width):
sh.width = sh.width + extra_width sh.width = sh.width + extra_width
cdef extern from *: cdef extern from *:
""" """
/* This is C code which will be put /* This is C code which will be put
* in the .c file output by Cython */ * in the .c file output by Cython */
static long square(long x) {return x * x;} static long square(long x) {return x * x;}
#define assign(x, y) ((x) = (y)) #define assign(x, y) ((x) = (y))
""" """
long square(long x) long square(long x)
void assign(long& x, long y) void assign(long& x, long y)
# delorean.pyx # delorean.pyx
cdef public struct Vehicle: cdef public struct Vehicle:
int speed int speed
float power float power
cdef api void activate(Vehicle *v): cdef api void activate(Vehicle *v):
if v.speed >= 88 and v.power >= 1.21: if v.speed >= 88 and v.power >= 1.21:
print("Time travel achieved") print("Time travel achieved")
\ No newline at end of file
from __future__ import print_function from __future__ import print_function
ctypedef fused char_or_float: ctypedef fused char_or_float:
char char
float float
cpdef char_or_float plus_one(char_or_float var): cpdef char_or_float plus_one(char_or_float var):
return var + 1 return var + 1
def show_me(): def show_me():
cdef: cdef:
char a = 127 char a = 127
float b = 127 float b = 127
print('char', plus_one(a)) print('char', plus_one(a))
print('float', plus_one(b)) print('float', plus_one(b))
from cpython.ref cimport PyObject from cpython.ref cimport PyObject
cdef extern from *: cdef extern from *:
ctypedef Py_ssize_t Py_intptr_t ctypedef Py_ssize_t Py_intptr_t
python_string = "foo" python_string = "foo"
cdef void* ptr = <void*>python_string cdef void* ptr = <void*>python_string
cdef Py_intptr_t adress_in_c = <Py_intptr_t>ptr cdef Py_intptr_t adress_in_c = <Py_intptr_t>ptr
address_from_void = adress_in_c # address_from_void is a python int address_from_void = adress_in_c # address_from_void is a python int
cdef PyObject* ptr2 = <PyObject*>python_string cdef PyObject* ptr2 = <PyObject*>python_string
cdef Py_intptr_t address_in_c2 = <Py_intptr_t>ptr2 cdef Py_intptr_t address_in_c2 = <Py_intptr_t>ptr2
address_from_PyObject = address_in_c2 # address_from_PyObject is a python int address_from_PyObject = address_in_c2 # address_from_PyObject is a python int
assert address_from_void == address_from_PyObject == id(python_string) assert address_from_void == address_from_PyObject == id(python_string)
print(<object>ptr) # Prints "foo" print(<object>ptr) # Prints "foo"
print(<object>ptr2) # prints "foo" print(<object>ptr2) # prints "foo"
from __future__ import print_function from __future__ import print_function
cdef: cdef:
struct Spam: struct Spam:
int tons int tons
int i int i
float a float a
Spam *p Spam *p
void f(Spam *s): void f(Spam *s):
print(s.tons, "Tons of spam") print(s.tons, "Tons of spam")
from __future__ import print_function from __future__ import print_function
DEF FavouriteFood = u"spam" DEF FavouriteFood = u"spam"
DEF ArraySize = 42 DEF ArraySize = 42
DEF OtherArraySize = 2 * ArraySize + 17 DEF OtherArraySize = 2 * ArraySize + 17
cdef int a1[ArraySize] cdef int a1[ArraySize]
cdef int a2[OtherArraySize] cdef int a2[OtherArraySize]
print("I like", FavouriteFood) print("I like", FavouriteFood)
\ No newline at end of file
def f(a, b, *args, c, d = 42, e, **kwds): def f(a, b, *args, c, d = 42, e, **kwds):
... ...
# We cannot call f with less verbosity than this. # We cannot call f with less verbosity than this.
foo = f(4, "bar", c=68, e=1.0) foo = f(4, "bar", c=68, e=1.0)
def g(a, b, *, c, d): def g(a, b, *, c, d):
... ...
# We cannot call g with less verbosity than this. # We cannot call g with less verbosity than this.
foo = g(4.0, "something", c=68, d="other") foo = g(4.0, "something", c=68, d="other")
from libc.stdio cimport FILE, fopen from libc.stdio cimport FILE, fopen
from libc.stdlib cimport malloc, free from libc.stdlib cimport malloc, free
from cpython.exc cimport PyErr_SetFromErrnoWithFilenameObject from cpython.exc cimport PyErr_SetFromErrnoWithFilenameObject
def open_file(): def open_file():
cdef FILE* p cdef FILE* p
p = fopen("spam.txt", "r") p = fopen("spam.txt", "r")
if p is NULL: if p is NULL:
PyErr_SetFromErrnoWithFilenameObject(OSError, "spam.txt") PyErr_SetFromErrnoWithFilenameObject(OSError, "spam.txt")
... ...
def allocating_memory(number=10): def allocating_memory(number=10):
cdef double *my_array = <double *> malloc(number * sizeof(double)) cdef double *my_array = <double *> malloc(number * sizeof(double))
if not my_array: # same as 'is NULL' above if not my_array: # same as 'is NULL' above
raise MemoryError() raise MemoryError()
... ...
free(my_array) free(my_array)
from __future__ import print_function from __future__ import print_function
cdef class A: cdef class A:
cdef foo(self): cdef foo(self):
print("A") print("A")
cdef class B(A): cdef class B(A):
cdef foo(self, x=None): cdef foo(self, x=None):
print("B", x) print("B", x)
cdef class C(B): cdef class C(B):
cpdef foo(self, x=True, int k=3): cpdef foo(self, x=True, int k=3):
print("C", x, k) print("C", x, k)
from __future__ import print_function from __future__ import print_function
cdef class A: cdef class A:
cdef foo(self): cdef foo(self):
print("A") print("A")
cdef class B(A): cdef class B(A):
cpdef foo(self): cpdef foo(self):
print("B") print("B")
class C(B): # NOTE: not cdef class class C(B): # NOTE: not cdef class
def foo(self): def foo(self):
print("C") print("C")
cdef struct Grail: cdef struct Grail:
int age int age
float volume float volume
cdef union Food: cdef union Food:
char *spam char *spam
float *eggs float *eggs
cdef enum CheeseType: cdef enum CheeseType:
cheddar, edam, cheddar, edam,
camembert camembert
cdef enum CheeseState: cdef enum CheeseState:
hard = 1 hard = 1
soft = 2 soft = 2
runny = 3 runny = 3
import numpy as np import numpy as np
def add_one(int[:,:] buf): def add_one(int[:,:] buf):
for x in range(buf.shape[0]): for x in range(buf.shape[0]):
for y in range(buf.shape[1]): for y in range(buf.shape[1]):
buf[x, y] += 1 buf[x, y] += 1
# exporting_object must be a Python object # exporting_object must be a Python object
# implementing the buffer interface, e.g. a numpy array. # implementing the buffer interface, e.g. a numpy array.
exporting_object = np.zeros((10, 20), dtype=np.intc) exporting_object = np.zeros((10, 20), dtype=np.intc)
add_one(exporting_object) add_one(exporting_object)
import numpy as np import numpy as np
cdef int[:, :, :] to_view, from_view cdef int[:, :, :] to_view, from_view
to_view = np.empty((20, 15, 30), dtype=np.intc) to_view = np.empty((20, 15, 30), dtype=np.intc)
from_view = np.ones((20, 15, 30), dtype=np.intc) from_view = np.ones((20, 15, 30), dtype=np.intc)
# copy the elements in from_view to to_view # copy the elements in from_view to to_view
to_view[...] = from_view to_view[...] = from_view
# or # or
to_view[:] = from_view to_view[:] = from_view
# or # or
to_view[:, :, :] = from_view to_view[:, :, :] = from_view
from cython cimport view from cython cimport view
# direct access in both dimensions, strided in the first dimension, contiguous in the last # direct access in both dimensions, strided in the first dimension, contiguous in the last
cdef int[:, ::view.contiguous] a cdef int[:, ::view.contiguous] a
# contiguous list of pointers to contiguous lists of ints # contiguous list of pointers to contiguous lists of ints
cdef int[::view.indirect_contiguous, ::1] b cdef int[::view.indirect_contiguous, ::1] b
# direct or indirect in the first dimension, direct in the second dimension # direct or indirect in the first dimension, direct in the second dimension
# strided in both dimensions # strided in both dimensions
cdef int[::view.generic, :] c cdef int[::view.generic, :] c
from cython cimport view from cython cimport view
# VALID # VALID
cdef int[::view.indirect, ::1, :] a cdef int[::view.indirect, ::1, :] a
cdef int[::view.indirect, :, ::1] b cdef int[::view.indirect, :, ::1] b
cdef int[::view.indirect_contiguous, ::1, :] c cdef int[::view.indirect_contiguous, ::1, :] c
cdef extern from "C_func_file.c": cdef extern from "C_func_file.c":
# C is include here so that it doesn't need to be compiled externally # C is include here so that it doesn't need to be compiled externally
pass pass
cdef extern from "C_func_file.h": cdef extern from "C_func_file.h":
void multiply_by_10_in_C(double *, unsigned int) void multiply_by_10_in_C(double *, unsigned int)
import numpy as np import numpy as np
def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array
if not arr.flags['C_CONTIGUOUS']: if not arr.flags['C_CONTIGUOUS']:
arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array. arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array.
cdef double[::1] arr_memview = arr cdef double[::1] arr_memview = arr
multiply_by_10_in_C(&arr_memview[0], arr_memview.shape[0]) multiply_by_10_in_C(&arr_memview[0], arr_memview.shape[0])
return arr return arr
a = np.ones(5, dtype=np.double) a = np.ones(5, dtype=np.double)
print(multiply_by_10(a)) print(multiply_by_10(a))
b = np.ones(10, dtype=np.double) b = np.ones(10, dtype=np.double)
b = b[::2] # b is not contiguous. b = b[::2] # b is not contiguous.
print(multiply_by_10(b)) # but our function still works as expected. print(multiply_by_10(b)) # but our function still works as expected.
import numpy as np import numpy as np
def process_buffer(int[:,:] input_view not None, def process_buffer(int[:,:] input_view not None,
int[:,:] output_view=None): int[:,:] output_view=None):
if output_view is None: if output_view is None:
# Creating a default view, e.g. # Creating a default view, e.g.
output_view = np.empty_like(input_view) output_view = np.empty_like(input_view)
# process 'input_view' into 'output_view' # process 'input_view' into 'output_view'
return output_view return output_view
import numpy as np import numpy as np
cdef const double[:] myslice # const item type => read-only view cdef const double[:] myslice # const item type => read-only view
a = np.linspace(0, 10, num=50) a = np.linspace(0, 10, num=50)
a.setflags(write=False) a.setflags(write=False)
myslice = a myslice = a
import numpy as np import numpy as np
exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20)) exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20))
cdef int[:, :, :] my_view = exporting_object cdef int[:, :, :] my_view = exporting_object
# These are all equivalent # These are all equivalent
my_view[10] my_view[10]
my_view[10, :, :] my_view[10, :, :]
my_view[10, ...] my_view[10, ...]
import numpy as np import numpy as np
array = np.arange(20, dtype=np.intc).reshape((2, 10)) array = np.arange(20, dtype=np.intc).reshape((2, 10))
cdef int[:, ::1] c_contig = array cdef int[:, ::1] c_contig = array
cdef int[::1, :] f_contig = c_contig.T cdef int[::1, :] f_contig = c_contig.T
cdef bint is_y_in(const unsigned char[:] string_view): cdef bint is_y_in(const unsigned char[:] string_view):
cdef int i cdef int i
for i in range(string_view.shape[0]): for i in range(string_view.shape[0]):
if string_view[i] == b'y': if string_view[i] == b'y':
return True return True
return False return False
print(is_y_in(b'hello world')) # False print(is_y_in(b'hello world')) # False
print(is_y_in(b'hello Cython')) # True print(is_y_in(b'hello Cython')) # True
# cython: infer_types=True # cython: infer_types=True
import numpy as np import numpy as np
cimport cython cimport cython
ctypedef fused my_type: ctypedef fused my_type:
int int
double double
long long long long
cdef my_type clip(my_type a, my_type min_value, my_type max_value): cdef my_type clip(my_type a, my_type min_value, my_type max_value):
return min(max(a, min_value), max_value) return min(max(a, min_value), max_value)
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c): def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c):
x_max = array_1.shape[0] x_max = array_1.shape[0]
y_max = array_1.shape[1] y_max = array_1.shape[1]
assert tuple(array_1.shape) == tuple(array_2.shape) assert tuple(array_1.shape) == tuple(array_2.shape)
if my_type is int: if my_type is int:
dtype = np.intc dtype = np.intc
elif my_type is double: elif my_type is double:
dtype = np.double dtype = np.double
elif my_type is cython.longlong: elif my_type is cython.longlong:
dtype = np.longlong dtype = np.longlong
result = np.zeros((x_max, y_max), dtype=dtype) result = np.zeros((x_max, y_max), dtype=dtype)
cdef my_type[:, ::1] result_view = result cdef my_type[:, ::1] result_view = result
cdef my_type tmp cdef my_type tmp
cdef Py_ssize_t x, y cdef Py_ssize_t x, y
for x in range(x_max): for x in range(x_max):
for y in range(y_max): for y in range(y_max):
tmp = clip(array_1[x, y], 2, 10) tmp = clip(array_1[x, y], 2, 10)
tmp = tmp * a + array_2[x, y] * b tmp = tmp * a + array_2[x, y] * b
result_view[x, y] = tmp + c result_view[x, y] = tmp + c
return result return result
# cython: infer_types=True # cython: infer_types=True
import numpy as np import numpy as np
cimport cython cimport cython
DTYPE = np.intc DTYPE = np.intc
cdef int clip(int a, int min_value, int max_value): cdef int clip(int a, int min_value, int max_value):
return min(max(a, min_value), max_value) return min(max(a, min_value), max_value)
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
def compute(int[:, ::1] array_1, int[:, ::1] array_2, int a, int b, int c): def compute(int[:, ::1] array_1, int[:, ::1] array_2, int a, int b, int c):
x_max = array_1.shape[0] x_max = array_1.shape[0]
y_max = array_1.shape[1] y_max = array_1.shape[1]
assert tuple(array_1.shape) == tuple(array_2.shape) assert tuple(array_1.shape) == tuple(array_2.shape)
result = np.zeros((x_max, y_max), dtype=DTYPE) result = np.zeros((x_max, y_max), dtype=DTYPE)
cdef int[:, ::1] result_view = result cdef int[:, ::1] result_view = result
cdef int tmp cdef int tmp
cdef Py_ssize_t x, y cdef Py_ssize_t x, y
for x in range(x_max): for x in range(x_max):
for y in range(y_max): for y in range(y_max):
tmp = clip(array_1[x, y], 2, 10) tmp = clip(array_1[x, y], 2, 10)
tmp = tmp * a + array_2[x, y] * b tmp = tmp * a + array_2[x, y] * b
result_view[x, y] = tmp + c result_view[x, y] = tmp + c
return result return result
import numpy as np import numpy as np
DTYPE = np.intc DTYPE = np.intc
cdef int clip(int a, int min_value, int max_value): cdef int clip(int a, int min_value, int max_value):
return min(max(a, min_value), max_value) return min(max(a, min_value), max_value)
def compute(int[:, :] array_1, int[:, :] array_2, int a, int b, int c): def compute(int[:, :] array_1, int[:, :] array_2, int a, int b, int c):
cdef Py_ssize_t x_max = array_1.shape[0] cdef Py_ssize_t x_max = array_1.shape[0]
cdef Py_ssize_t y_max = array_1.shape[1] cdef Py_ssize_t y_max = array_1.shape[1]
# array_1.shape is now a C array, no it's not possible # array_1.shape is now a C array, no it's not possible
# to compare it simply by using == without a for-loop. # to compare it simply by using == without a for-loop.
# To be able to compare it to array_2.shape easily, # To be able to compare it to array_2.shape easily,
# we convert them both to Python tuples. # we convert them both to Python tuples.
assert tuple(array_1.shape) == tuple(array_2.shape) assert tuple(array_1.shape) == tuple(array_2.shape)
result = np.zeros((x_max, y_max), dtype=DTYPE) result = np.zeros((x_max, y_max), dtype=DTYPE)
cdef int[:, :] result_view = result cdef int[:, :] result_view = result
cdef int tmp cdef int tmp
cdef Py_ssize_t x, y cdef Py_ssize_t x, y
for x in range(x_max): for x in range(x_max):
for y in range(y_max): for y in range(y_max):
tmp = clip(array_1[x, y], 2, 10) tmp = clip(array_1[x, y], 2, 10)
tmp = tmp * a + array_2[x, y] * b tmp = tmp * a + array_2[x, y] * b
result_view[x, y] = tmp + c result_view[x, y] = tmp + c
return result return result
# tag: openmp # tag: openmp
# You can ignore the previous line. # You can ignore the previous line.
# It's for internal testing of the cython documentation. # It's for internal testing of the cython documentation.
# distutils: extra_compile_args=-fopenmp # distutils: extra_compile_args=-fopenmp
# distutils: extra_link_args=-fopenmp # distutils: extra_link_args=-fopenmp
import numpy as np import numpy as np
cimport cython cimport cython
from cython.parallel import prange from cython.parallel import prange
ctypedef fused my_type: ctypedef fused my_type:
int int
double double
long long long long
# We declare our plain c function nogil # We declare our plain c function nogil
cdef my_type clip(my_type a, my_type min_value, my_type max_value) nogil: cdef my_type clip(my_type a, my_type min_value, my_type max_value) nogil:
return min(max(a, min_value), max_value) return min(max(a, min_value), max_value)
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c): def compute(my_type[:, ::1] array_1, my_type[:, ::1] array_2, my_type a, my_type b, my_type c):
cdef Py_ssize_t x_max = array_1.shape[0] cdef Py_ssize_t x_max = array_1.shape[0]
cdef Py_ssize_t y_max = array_1.shape[1] cdef Py_ssize_t y_max = array_1.shape[1]
assert tuple(array_1.shape) == tuple(array_2.shape) assert tuple(array_1.shape) == tuple(array_2.shape)
if my_type is int: if my_type is int:
dtype = np.intc dtype = np.intc
elif my_type is double: elif my_type is double:
dtype = np.double dtype = np.double
elif my_type is cython.longlong: elif my_type is cython.longlong:
dtype = np.longlong dtype = np.longlong
result = np.zeros((x_max, y_max), dtype=dtype) result = np.zeros((x_max, y_max), dtype=dtype)
cdef my_type[:, ::1] result_view = result cdef my_type[:, ::1] result_view = result
cdef my_type tmp cdef my_type tmp
cdef Py_ssize_t x, y cdef Py_ssize_t x, y
# We use prange here. # We use prange here.
for x in prange(x_max, nogil=True): for x in prange(x_max, nogil=True):
for y in range(y_max): for y in range(y_max):
tmp = clip(array_1[x, y], 2, 10) tmp = clip(array_1[x, y], 2, 10)
tmp = tmp * a + array_2[x, y] * b tmp = tmp * a + array_2[x, y] * b
result_view[x, y] = tmp + c result_view[x, y] = tmp + c
return result return result
import numpy as np import numpy as np
def clip(a, min_value, max_value): def clip(a, min_value, max_value):
return min(max(a, min_value), max_value) return min(max(a, min_value), max_value)
def compute(array_1, array_2, a, b, c): def compute(array_1, array_2, a, b, c):
""" """
This function must implement the formula This function must implement the formula
np.clip(array_1, 2, 10) * a + array_2 * b + c np.clip(array_1, 2, 10) * a + array_2 * b + c
array_1 and array_2 are 2D. array_1 and array_2 are 2D.
""" """
x_max = array_1.shape[0] x_max = array_1.shape[0]
y_max = array_1.shape[1] y_max = array_1.shape[1]
assert array_1.shape == array_2.shape assert array_1.shape == array_2.shape
result = np.zeros((x_max, y_max), dtype=array_1.dtype) result = np.zeros((x_max, y_max), dtype=array_1.dtype)
for x in range(x_max): for x in range(x_max):
for y in range(y_max): for y in range(y_max):
tmp = clip(array_1[x, y], 2, 10) tmp = clip(array_1[x, y], 2, 10)
tmp = tmp * a + array_2[x, y] * b tmp = tmp * a + array_2[x, y] * b
result[x, y] = tmp + c result[x, y] = tmp + c
return result return result
import numpy as np import numpy as np
# We now need to fix a datatype for our arrays. I've used the variable # We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime # DTYPE for this, which is assigned to the usual NumPy runtime
# type info object. # type info object.
DTYPE = np.intc DTYPE = np.intc
# cdef means here that this function is a plain C function (so faster). # cdef means here that this function is a plain C function (so faster).
# To get all the benefits, we type the arguments and the return value. # To get all the benefits, we type the arguments and the return value.
cdef int clip(int a, int min_value, int max_value): cdef int clip(int a, int min_value, int max_value):
return min(max(a, min_value), max_value) return min(max(a, min_value), max_value)
def compute(array_1, array_2, int a, int b, int c): def compute(array_1, array_2, int a, int b, int c):
# The "cdef" keyword is also used within functions to type variables. It # The "cdef" keyword is also used within functions to type variables. It
# can only be used at the top indentation level (there are non-trivial # can only be used at the top indentation level (there are non-trivial
# problems with allowing them in other places, though we'd love to see # problems with allowing them in other places, though we'd love to see
# good and thought out proposals for it). # good and thought out proposals for it).
cdef Py_ssize_t x_max = array_1.shape[0] cdef Py_ssize_t x_max = array_1.shape[0]
cdef Py_ssize_t y_max = array_1.shape[1] cdef Py_ssize_t y_max = array_1.shape[1]
assert array_1.shape == array_2.shape assert array_1.shape == array_2.shape
assert array_1.dtype == DTYPE assert array_1.dtype == DTYPE
assert array_2.dtype == DTYPE assert array_2.dtype == DTYPE
result = np.zeros((x_max, y_max), dtype=DTYPE) result = np.zeros((x_max, y_max), dtype=DTYPE)
# It is very important to type ALL your variables. You do not get any # It is very important to type ALL your variables. You do not get any
# warnings if not, only much slower code (they are implicitly typed as # warnings if not, only much slower code (they are implicitly typed as
# Python objects). # Python objects).
# For the "tmp" variable, we want to use the same data type as is # For the "tmp" variable, we want to use the same data type as is
# stored in the array, so we use int because it correspond to np.intc. # stored in the array, so we use int because it correspond to np.intc.
# NB! An important side-effect of this is that if "tmp" overflows its # NB! An important side-effect of this is that if "tmp" overflows its
# datatype size, it will simply wrap around like in C, rather than raise # datatype size, it will simply wrap around like in C, rather than raise
# an error like in Python. # an error like in Python.
cdef int tmp cdef int tmp
# Py_ssize_t is the proper C type for Python array indices. # Py_ssize_t is the proper C type for Python array indices.
cdef Py_ssize_t x, y cdef Py_ssize_t x, y
for x in range(x_max): for x in range(x_max):
for y in range(y_max): for y in range(y_max):
tmp = clip(array_1[x, y], 2, 10) tmp = clip(array_1[x, y], 2, 10)
tmp = tmp * a + array_2[x, y] * b tmp = tmp * a + array_2[x, y] * b
result[x, y] = tmp + c result[x, y] = tmp + c
return result return result
from cython.parallel import prange from cython.parallel import prange
cdef int func(Py_ssize_t n): cdef int func(Py_ssize_t n):
cdef Py_ssize_t i cdef Py_ssize_t i
for i in prange(n, nogil=True): for i in prange(n, nogil=True):
if i == 8: if i == 8:
with gil: with gil:
raise Exception() raise Exception()
elif i == 4: elif i == 4:
break break
elif i == 2: elif i == 2:
return i return i
# tag: openmp # tag: openmp
# You can ignore the previous line. # You can ignore the previous line.
# It's for internal testing of the Cython documentation. # It's for internal testing of the Cython documentation.
from cython.parallel cimport parallel from cython.parallel cimport parallel
cimport openmp cimport openmp
cdef int num_threads cdef int num_threads
openmp.omp_set_dynamic(1) openmp.omp_set_dynamic(1)
with nogil, parallel(): with nogil, parallel():
num_threads = openmp.omp_get_num_threads() num_threads = openmp.omp_get_num_threads()
# ... # ...
from distutils.core import setup from distutils.core import setup
from distutils.extension import Extension from distutils.extension import Extension
from Cython.Build import cythonize from Cython.Build import cythonize
ext_modules = [ ext_modules = [
Extension( Extension(
"hello", "hello",
["hello.pyx"], ["hello.pyx"],
extra_compile_args=['-fopenmp'], extra_compile_args=['-fopenmp'],
extra_link_args=['-fopenmp'], extra_link_args=['-fopenmp'],
) )
] ]
setup( setup(
name='hello-parallel-world', name='hello-parallel-world',
ext_modules=cythonize(ext_modules), ext_modules=cythonize(ext_modules),
) )
from cython.parallel import prange from cython.parallel import prange
cdef int i cdef int i
cdef int n = 30 cdef int n = 30
cdef int sum = 0 cdef int sum = 0
for i in prange(n, nogil=True): for i in prange(n, nogil=True):
sum += i sum += i
print(sum) print(sum)
cimport shrubbing cimport shrubbing
import shrubbing import shrubbing
def main(): def main():
cdef shrubbing.Shrubbery sh cdef shrubbing.Shrubbery sh
sh = shrubbing.standard_shrubbery() sh = shrubbing.standard_shrubbery()
print("Shrubbery size is", sh.width, 'x', sh.length) print("Shrubbery size is", sh.width, 'x', sh.length)
cimport c_lunch cimport c_lunch
def eject_tomato(float speed): def eject_tomato(float speed):
c_lunch.eject_tomato(speed) c_lunch.eject_tomato(speed)
from __future__ import print_function from __future__ import print_function
cimport dishes cimport dishes
from dishes cimport spamdish from dishes cimport spamdish
cdef void prepare(spamdish *d): cdef void prepare(spamdish *d):
d.oz_of_spam = 42 d.oz_of_spam = 42
d.filler = dishes.sausage d.filler = dishes.sausage
def serve(): def serve():
cdef spamdish d cdef spamdish d
prepare(&d) prepare(&d)
print(f'{d.oz_of_spam} oz spam, filler no. {d.filler}') print(f'{d.oz_of_spam} oz spam, filler no. {d.filler}')
from distutils.core import setup from distutils.core import setup
from Cython.Build import cythonize from Cython.Build import cythonize
setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"])) setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"]))
cdef class Shrubbery: cdef class Shrubbery:
def __cinit__(self, int w, int l): def __cinit__(self, int w, int l):
self.width = w self.width = w
self.length = l self.length = l
def standard_shrubbery(): def standard_shrubbery():
return Shrubbery(3, 7) return Shrubbery(3, 7)
from __future__ import print_function from __future__ import print_function
from volume cimport cube from volume cimport cube
def menu(description, size): def menu(description, size):
print(description, ":", cube(size), print(description, ":", cube(size),
"cubic metres of spam") "cubic metres of spam")
menu("Entree", 1) menu("Entree", 1)
menu("Main course", 3) menu("Main course", 3)
menu("Dessert", 2) menu("Dessert", 2)
cdef float cube(float x): cdef float cube(float x):
return x * x * x return x * x * x
# distutils: language = c++ # distutils: language = c++
from Rectangle cimport Rectangle from Rectangle cimport Rectangle
def main(): def main():
rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap
try: try:
rec_area = rec_ptr.getArea() rec_area = rec_ptr.getArea()
finally: finally:
del rec_ptr # delete heap allocated object del rec_ptr # delete heap allocated object
cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack
# distutils: language = c++ # distutils: language = c++
cdef extern from "<algorithm>" namespace "std": cdef extern from "<algorithm>" namespace "std":
T max[T](T a, T b) T max[T](T a, T b)
print(max[long](3, 4)) print(max[long](3, 4))
print(max(1.5, 2.5)) # simple template argument deduction print(max(1.5, 2.5)) # simple template argument deduction
# distutils: language = c++ # distutils: language = c++
from libcpp.vector cimport vector from libcpp.vector cimport vector
def main(): def main():
cdef vector[int] v = [4, 6, 5, 10, 3] cdef vector[int] v = [4, 6, 5, 10, 3]
cdef int value cdef int value
for value in v: for value in v:
print(value) print(value)
return [x*x for x in v if x % 2 == 0] return [x*x for x in v if x % 2 == 0]
# distutils: language = c++ # distutils: language = c++
cdef extern from "<vector>" namespace "std": cdef extern from "<vector>" namespace "std":
cdef cppclass vector[T]: cdef cppclass vector[T]:
cppclass iterator: cppclass iterator:
T operator*() T operator*()
iterator operator++() iterator operator++()
bint operator==(iterator) bint operator==(iterator)
bint operator!=(iterator) bint operator!=(iterator)
vector() vector()
void push_back(T&) void push_back(T&)
T& operator[](int) T& operator[](int)
T& at(int) T& at(int)
iterator begin() iterator begin()
iterator end() iterator end()
cdef vector[int].iterator iter #iter is declared as being of type vector<int>::iterator cdef vector[int].iterator iter #iter is declared as being of type vector<int>::iterator
# distutils: language = c++ # distutils: language = c++
from libcpp.string cimport string from libcpp.string cimport string
from libcpp.vector cimport vector from libcpp.vector cimport vector
py_bytes_object = b'The knights who say ni' py_bytes_object = b'The knights who say ni'
py_unicode_object = u'Those who hear them seldom live to tell the tale.' py_unicode_object = u'Those who hear them seldom live to tell the tale.'
cdef string s = py_bytes_object cdef string s = py_bytes_object
print(s) # b'The knights who say ni' print(s) # b'The knights who say ni'
cdef string cpp_string = <string> py_unicode_object.encode('utf-8') cdef string cpp_string = <string> py_unicode_object.encode('utf-8')
print(cpp_string) # b'Those who hear them seldom live to tell the tale.' print(cpp_string) # b'Those who hear them seldom live to tell the tale.'
cdef vector[int] vect = range(1, 10, 2) cdef vector[int] vect = range(1, 10, 2)
print(vect) # [1, 3, 5, 7, 9] print(vect) # [1, 3, 5, 7, 9]
cdef vector[string] cpp_strings = b'It is a good shrubbery'.split() cdef vector[string] cpp_strings = b'It is a good shrubbery'.split()
print(cpp_strings[1]) # b'is' print(cpp_strings[1]) # b'is'
# distutils: language = c++ # distutils: language = c++
from Rectangle cimport Rectangle from Rectangle cimport Rectangle
cdef class PyRectangle: cdef class PyRectangle:
cdef Rectangle*c_rect # hold a pointer to the C++ instance which we're wrapping cdef Rectangle*c_rect # hold a pointer to the C++ instance which we're wrapping
def __cinit__(self, int x0, int y0, int x1, int y1): def __cinit__(self, int x0, int y0, int x1, int y1):
self.c_rect = new Rectangle(x0, y0, x1, y1) self.c_rect = new Rectangle(x0, y0, x1, y1)
def __dealloc__(self): def __dealloc__(self):
del self.c_rect del self.c_rect
# distutils: language = c++ # distutils: language = c++
# import dereference and increment operators # import dereference and increment operators
from cython.operator cimport dereference as deref, preincrement as inc from cython.operator cimport dereference as deref, preincrement as inc
cdef extern from "<vector>" namespace "std": cdef extern from "<vector>" namespace "std":
cdef cppclass vector[T]: cdef cppclass vector[T]:
cppclass iterator: cppclass iterator:
T operator*() T operator*()
iterator operator++() iterator operator++()
bint operator==(iterator) bint operator==(iterator)
bint operator!=(iterator) bint operator!=(iterator)
vector() vector()
void push_back(T&) void push_back(T&)
T& operator[](int) T& operator[](int)
T& at(int) T& at(int)
iterator begin() iterator begin()
iterator end() iterator end()
cdef vector[int] *v = new vector[int]() cdef vector[int] *v = new vector[int]()
cdef int i cdef int i
for i in range(10): for i in range(10):
v.push_back(i) v.push_back(i)
cdef vector[int].iterator it = v.begin() cdef vector[int].iterator it = v.begin()
while it != v.end(): while it != v.end():
print(deref(it)) print(deref(it))
inc(it) inc(it)
del v del v
# distutils: language = c++ # distutils: language = c++
from libcpp.vector cimport vector from libcpp.vector cimport vector
cdef vector[int] vect cdef vector[int] vect
cdef int i, x cdef int i, x
for i in range(10): for i in range(10):
vect.push_back(i) vect.push_back(i)
for i in range(10): for i in range(10):
print(vect[i]) print(vect[i])
for x in vect: for x in vect:
print(x) print(x)
# distutils: language = c++ # distutils: language = c++
from libcpp.vector cimport vector from libcpp.vector cimport vector
cdef class VectorStack: cdef class VectorStack:
cdef vector[int] v cdef vector[int] v
def push(self, x): def push(self, x):
self.v.push_back(x) self.v.push_back(x)
def pop(self): def pop(self):
if self.v.empty(): if self.v.empty():
raise IndexError() raise IndexError()
x = self.v.back() x = self.v.back()
self.v.pop_back() self.v.pop_back()
return x return x
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment