diff options
Diffstat (limited to 'docs/examples/userguide')
143 files changed, 2300 insertions, 974 deletions
diff --git a/docs/examples/userguide/buffer/matrix.py b/docs/examples/userguide/buffer/matrix.py new file mode 100644 index 000000000..0e431163d --- /dev/null +++ b/docs/examples/userguide/buffer/matrix.py @@ -0,0 +1,15 @@ +# distutils: language = c++ + +from cython.cimports.libcpp.vector import vector + +@cython.cclass +class Matrix: + ncols: cython.uint + v: vector[cython.float] + + def __cinit__(self, ncols: cython.uint): + self.ncols = ncols + + def add_row(self): + """Adds a row, initially zero-filled.""" + self.v.resize(self.v.size() + self.ncols) diff --git a/docs/examples/userguide/buffer/matrix.pyx b/docs/examples/userguide/buffer/matrix.pyx index abdb2d3c7..f2547f6c3 100644 --- a/docs/examples/userguide/buffer/matrix.pyx +++ b/docs/examples/userguide/buffer/matrix.pyx @@ -1,16 +1,15 @@ -# distutils: language = c++
-
-# matrix.pyx
-
-from libcpp.vector cimport vector
-
-cdef class Matrix:
- cdef unsigned ncols
- cdef vector[float] v
-
- def __cinit__(self, unsigned ncols):
- self.ncols = ncols
-
- def add_row(self):
- """Adds a row, initially zero-filled."""
- self.v.resize(self.v.size() + self.ncols)
+# distutils: language = c++ + +from libcpp.vector cimport vector + + +cdef class Matrix: + cdef unsigned ncols + cdef vector[float] v + + def __cinit__(self, unsigned ncols): + self.ncols = ncols + + def add_row(self): + """Adds a row, initially zero-filled.""" + self.v.resize(self.v.size() + self.ncols) diff --git a/docs/examples/userguide/buffer/matrix_with_buffer.py b/docs/examples/userguide/buffer/matrix_with_buffer.py new file mode 100644 index 000000000..34ccc6591 --- /dev/null +++ b/docs/examples/userguide/buffer/matrix_with_buffer.py @@ -0,0 +1,48 @@ +# distutils: language = c++ +from cython.cimports.cpython import Py_buffer +from cython.cimports.libcpp.vector import vector + +@cython.cclass +class Matrix: + ncols: cython.Py_ssize_t + shape: cython.Py_ssize_t[2] + strides: cython.Py_ssize_t[2] + v: vector[cython.float] + + def __cinit__(self, ncols: cython.Py_ssize_t): + self.ncols = ncols + + def add_row(self): + """Adds a row, initially zero-filled.""" + self.v.resize(self.v.size() + self.ncols) + + def __getbuffer__(self, buffer: cython.pointer(Py_buffer), flags: cython.int): + itemsize: cython.Py_ssize_t = cython.sizeof(self.v[0]) + + self.shape[0] = self.v.size() // self.ncols + self.shape[1] = self.ncols + + # Stride 1 is the distance, in bytes, between two items in a row; + # this is the distance between two adjacent items in the vector. + # Stride 0 is the distance between the first elements of adjacent rows. + self.strides[1] = cython.cast(cython.Py_ssize_t, ( + cython.cast(cython.p_char, cython.address(self.v[1])) + - cython.cast(cython.p_char, cython.address(self.v[0])) + ) + ) + self.strides[0] = self.ncols * self.strides[1] + + buffer.buf = cython.cast(cython.p_char, cython.address(self.v[0])) + buffer.format = 'f' # float + buffer.internal = cython.NULL # see References + buffer.itemsize = itemsize + buffer.len = self.v.size() * itemsize # product(shape) * itemsize + buffer.ndim = 2 + buffer.obj = self + buffer.readonly = 0 + buffer.shape = self.shape + buffer.strides = self.strides + buffer.suboffsets = cython.NULL # for pointer arrays only + + def __releasebuffer__(self, buffer: cython.pointer(Py_buffer)): + pass diff --git a/docs/examples/userguide/buffer/matrix_with_buffer.pyx b/docs/examples/userguide/buffer/matrix_with_buffer.pyx index 985991cbe..fc2c160f3 100644 --- a/docs/examples/userguide/buffer/matrix_with_buffer.pyx +++ b/docs/examples/userguide/buffer/matrix_with_buffer.pyx @@ -1,45 +1,48 @@ -# distutils: language = c++
-
-from cpython cimport Py_buffer
-from libcpp.vector cimport vector
-
-cdef class Matrix:
- cdef Py_ssize_t ncols
- cdef Py_ssize_t shape[2]
- cdef Py_ssize_t strides[2]
- cdef vector[float] v
-
- def __cinit__(self, Py_ssize_t ncols):
- self.ncols = ncols
-
- def add_row(self):
- """Adds a row, initially zero-filled."""
- self.v.resize(self.v.size() + self.ncols)
-
- def __getbuffer__(self, Py_buffer *buffer, int flags):
- cdef Py_ssize_t itemsize = sizeof(self.v[0])
-
- self.shape[0] = self.v.size() / self.ncols
- self.shape[1] = self.ncols
-
- # Stride 1 is the distance, in bytes, between two items in a row;
- # this is the distance between two adjacent items in the vector.
- # Stride 0 is the distance between the first elements of adjacent rows.
- self.strides[1] = <Py_ssize_t>( <char *>&(self.v[1])
- - <char *>&(self.v[0]))
- self.strides[0] = self.ncols * self.strides[1]
-
- buffer.buf = <char *>&(self.v[0])
- buffer.format = 'f' # float
- buffer.internal = NULL # see References
- buffer.itemsize = itemsize
- buffer.len = self.v.size() * itemsize # product(shape) * itemsize
- buffer.ndim = 2
- buffer.obj = self
- buffer.readonly = 0
- buffer.shape = self.shape
- buffer.strides = self.strides
- buffer.suboffsets = NULL # for pointer arrays only
-
- def __releasebuffer__(self, Py_buffer *buffer):
- pass
+# distutils: language = c++ +from cpython cimport Py_buffer +from libcpp.vector cimport vector + + +cdef class Matrix: + cdef Py_ssize_t ncols + cdef Py_ssize_t[2] shape + cdef Py_ssize_t[2] strides + cdef vector[float] v + + def __cinit__(self, Py_ssize_t ncols): + self.ncols = ncols + + def add_row(self): + """Adds a row, initially zero-filled.""" + self.v.resize(self.v.size() + self.ncols) + + def __getbuffer__(self, Py_buffer *buffer, int flags): + cdef Py_ssize_t itemsize = sizeof(self.v[0]) + + self.shape[0] = self.v.size() // self.ncols + self.shape[1] = self.ncols + + # Stride 1 is the distance, in bytes, between two items in a row; + # this is the distance between two adjacent items in the vector. + # Stride 0 is the distance between the first elements of adjacent rows. + self.strides[1] = <Py_ssize_t>( <char *>&(self.v[1]) + - <char *>&(self.v[0])) + + + + self.strides[0] = self.ncols * self.strides[1] + + buffer.buf = <char *>&(self.v[0]) + buffer.format = 'f' # float + buffer.internal = NULL # see References + buffer.itemsize = itemsize + buffer.len = self.v.size() * itemsize # product(shape) * itemsize + buffer.ndim = 2 + buffer.obj = self + buffer.readonly = 0 + buffer.shape = self.shape + buffer.strides = self.strides + buffer.suboffsets = NULL # for pointer arrays only + + def __releasebuffer__(self, Py_buffer *buffer): + pass diff --git a/docs/examples/userguide/buffer/view_count.py b/docs/examples/userguide/buffer/view_count.py new file mode 100644 index 000000000..6a0554abc --- /dev/null +++ b/docs/examples/userguide/buffer/view_count.py @@ -0,0 +1,30 @@ +# distutils: language = c++ + +from cython.cimports.cpython import Py_buffer +from cython.cimports.libcpp.vector import vector + +@cython.cclass +class Matrix: + + view_count: cython.int + + ncols: cython.Py_ssize_t + v: vector[cython.float] + # ... + + def __cinit__(self, ncols: cython.Py_ssize_t): + self.ncols = ncols + self.view_count = 0 + + def add_row(self): + if self.view_count > 0: + raise ValueError("can't add row while being viewed") + self.v.resize(self.v.size() + self.ncols) + + def __getbuffer__(self, buffer: cython.pointer(Py_buffer), flags: cython.int): + # ... as before + + self.view_count += 1 + + def __releasebuffer__(self, buffer: cython.pointer(Py_buffer)): + self.view_count -= 1 diff --git a/docs/examples/userguide/buffer/view_count.pyx b/docs/examples/userguide/buffer/view_count.pyx index ee8d5085d..8c4b1d524 100644 --- a/docs/examples/userguide/buffer/view_count.pyx +++ b/docs/examples/userguide/buffer/view_count.pyx @@ -1,29 +1,30 @@ -# distutils: language = c++
-
-from cpython cimport Py_buffer
-from libcpp.vector cimport vector
-
-cdef class Matrix:
-
- cdef int view_count
-
- cdef Py_ssize_t ncols
- cdef vector[float] v
- # ...
-
- def __cinit__(self, Py_ssize_t ncols):
- self.ncols = ncols
- self.view_count = 0
-
- def add_row(self):
- if self.view_count > 0:
- raise ValueError("can't add row while being viewed")
- self.v.resize(self.v.size() + self.ncols)
-
- def __getbuffer__(self, Py_buffer *buffer, int flags):
- # ... as before
-
- self.view_count += 1
-
- def __releasebuffer__(self, Py_buffer *buffer):
- self.view_count -= 1
\ No newline at end of file +# distutils: language = c++ + +from cpython cimport Py_buffer +from libcpp.vector cimport vector + + +cdef class Matrix: + + cdef int view_count + + cdef Py_ssize_t ncols + cdef vector[float] v + # ... + + def __cinit__(self, Py_ssize_t ncols): + self.ncols = ncols + self.view_count = 0 + + def add_row(self): + if self.view_count > 0: + raise ValueError("can't add row while being viewed") + self.v.resize(self.v.size() + self.ncols) + + def __getbuffer__(self, Py_buffer *buffer, int flags): + # ... as before + + self.view_count += 1 + + def __releasebuffer__(self, Py_buffer *buffer): + self.view_count -= 1 diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle.py b/docs/examples/userguide/early_binding_for_speed/rectangle.py new file mode 100644 index 000000000..cd534d051 --- /dev/null +++ b/docs/examples/userguide/early_binding_for_speed/rectangle.py @@ -0,0 +1,22 @@ +@cython.cclass +class Rectangle: + x0: cython.int + y0: cython.int + x1: cython.int + y1: cython.int + + def __init__(self, x0: cython.int, y0: cython.int, x1: cython.int, y1: cython.int): + self.x0 = x0 + self.y0 = y0 + self.x1 = x1 + self.y1 = y1 + + def area(self): + area = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + +def rectArea(x0, y0, x1, y1): + rect = Rectangle(x0, y0, x1, y1) + return rect.area() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle.pyx b/docs/examples/userguide/early_binding_for_speed/rectangle.pyx index ffc5593b0..b58f6534b 100644 --- a/docs/examples/userguide/early_binding_for_speed/rectangle.pyx +++ b/docs/examples/userguide/early_binding_for_speed/rectangle.pyx @@ -1,19 +1,22 @@ -cdef class Rectangle:
- cdef int x0, y0
- cdef int x1, y1
-
- def __init__(self, int x0, int y0, int x1, int y1):
- self.x0 = x0
- self.y0 = y0
- self.x1 = x1
- self.y1 = y1
-
- def area(self):
- area = (self.x1 - self.x0) * (self.y1 - self.y0)
- if area < 0:
- area = -area
- return area
-
-def rectArea(x0, y0, x1, y1):
- rect = Rectangle(x0, y0, x1, y1)
- return rect.area()
+ +cdef class Rectangle: + cdef int x0, y0 + cdef int x1, y1 + + + + def __init__(self, int x0, int y0, int x1, int y1): + self.x0 = x0 + self.y0 = y0 + self.x1 = x1 + self.y1 = y1 + + def area(self): + area = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + +def rectArea(x0, y0, x1, y1): + rect = Rectangle(x0, y0, x1, y1) + return rect.area() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.py b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.py new file mode 100644 index 000000000..ee2a14fb8 --- /dev/null +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.py @@ -0,0 +1,26 @@ +@cython.cclass +class Rectangle: + x0: cython.int + y0: cython.int + x1: cython.int + y1: cython.int + + def __init__(self, x0: cython.int, y0: cython.int, x1: cython.int, y1: cython.int): + self.x0 = x0 + self.y0 = y0 + self.x1 = x1 + self.y1 = y1 + + @cython.cfunc + def _area(self) -> cython.int: + area: cython.int = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + + def area(self): + return self._area() + +def rectArea(x0, y0, x1, y1): + rect: Rectangle = Rectangle(x0, y0, x1, y1) + return rect._area() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx index 5502b4568..3b64d766b 100644 --- a/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cdef.pyx @@ -1,22 +1,26 @@ -cdef class Rectangle:
- cdef int x0, y0
- cdef int x1, y1
-
- def __init__(self, int x0, int y0, int x1, int y1):
- self.x0 = x0
- self.y0 = y0
- self.x1 = x1
- self.y1 = y1
-
- cdef int _area(self):
- area = (self.x1 - self.x0) * (self.y1 - self.y0)
- if area < 0:
- area = -area
- return area
-
- def area(self):
- return self._area()
-
-def rectArea(x0, y0, x1, y1):
- rect = Rectangle(x0, y0, x1, y1)
- return rect.area()
+ +cdef class Rectangle: + cdef int x0, y0 + cdef int x1, y1 + + + + def __init__(self, int x0, int y0, int x1, int y1): + self.x0 = x0 + self.y0 = y0 + self.x1 = x1 + self.y1 = y1 + + + cdef int _area(self): + cdef int area = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + + def area(self): + return self._area() + +def rectArea(x0, y0, x1, y1): + cdef Rectangle rect = Rectangle(x0, y0, x1, y1) + return rect._area() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.py b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.py new file mode 100644 index 000000000..670f340a4 --- /dev/null +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.py @@ -0,0 +1,23 @@ +@cython.cclass +class Rectangle: + x0: cython.int + y0: cython.int + x1: cython.int + y1: cython.int + + def __init__(self, x0: cython.int, y0: cython.int, x1: cython.int, y1: cython.int): + self.x0 = x0 + self.y0 = y0 + self.x1 = x1 + self.y1 = y1 + + @cython.ccall + def area(self)-> cython.int: + area: cython.int = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + +def rectArea(x0, y0, x1, y1): + rect: Rectangle = Rectangle(x0, y0, x1, y1) + return rect.area() diff --git a/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx index 01df3759f..53f2a8ad2 100644 --- a/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx +++ b/docs/examples/userguide/early_binding_for_speed/rectangle_cpdef.pyx @@ -1,19 +1,23 @@ -cdef class Rectangle:
- cdef int x0, y0
- cdef int x1, y1
-
- def __init__(self, int x0, int y0, int x1, int y1):
- self.x0 = x0
- self.y0 = y0
- self.x1 = x1
- self.y1 = y1
-
- cpdef int area(self):
- area = (self.x1 - self.x0) * (self.y1 - self.y0)
- if area < 0:
- area = -area
- return area
-
-def rectArea(x0, y0, x1, y1):
- rect = Rectangle(x0, y0, x1, y1)
- return rect.area()
+ +cdef class Rectangle: + cdef int x0, y0 + cdef int x1, y1 + + + + def __init__(self, int x0, int y0, int x1, int y1): + self.x0 = x0 + self.y0 = y0 + self.x1 = x1 + self.y1 = y1 + + + cpdef int area(self): + cdef int area = (self.x1 - self.x0) * (self.y1 - self.y0) + if area < 0: + area = -area + return area + +def rectArea(x0, y0, x1, y1): + cdef Rectangle rect = Rectangle(x0, y0, x1, y1) + return rect.area() diff --git a/docs/examples/userguide/extension_types/c_property.pyx b/docs/examples/userguide/extension_types/c_property.pyx new file mode 100644 index 000000000..b759ceec1 --- /dev/null +++ b/docs/examples/userguide/extension_types/c_property.pyx @@ -0,0 +1,20 @@ +cdef extern from "complexobject.h": + + struct Py_complex: + double real + double imag + + ctypedef class __builtin__.complex [object PyComplexObject]: + cdef Py_complex cval + + @property + cdef inline double real(self): + return self.cval.real + + @property + cdef inline double imag(self): + return self.cval.imag + + +def cprint(complex c): + print(f"{c.real :.4f}{c.imag :+.4f}j") # uses C calls to the above property methods. diff --git a/docs/examples/userguide/extension_types/cheesy.py b/docs/examples/userguide/extension_types/cheesy.py new file mode 100644 index 000000000..0995c3993 --- /dev/null +++ b/docs/examples/userguide/extension_types/cheesy.py @@ -0,0 +1,36 @@ +import cython + +@cython.cclass +class CheeseShop: + + cheeses: object + + def __cinit__(self): + self.cheeses = [] + + @property + def cheese(self): + return "We don't have: %s" % self.cheeses + + @cheese.setter + def cheese(self, value): + self.cheeses.append(value) + + @cheese.deleter + def cheese(self): + del self.cheeses[:] + +# Test input +from cheesy import CheeseShop + +shop = CheeseShop() +print(shop.cheese) + +shop.cheese = "camembert" +print(shop.cheese) + +shop.cheese = "cheddar" +print(shop.cheese) + +del shop.cheese +print(shop.cheese) diff --git a/docs/examples/userguide/extension_types/cheesy.pyx b/docs/examples/userguide/extension_types/cheesy.pyx new file mode 100644 index 000000000..2859d848f --- /dev/null +++ b/docs/examples/userguide/extension_types/cheesy.pyx @@ -0,0 +1,36 @@ + + + +cdef class CheeseShop: + + cdef object cheeses + + def __cinit__(self): + self.cheeses = [] + + @property + def cheese(self): + return "We don't have: %s" % self.cheeses + + @cheese.setter + def cheese(self, value): + self.cheeses.append(value) + + @cheese.deleter + def cheese(self): + del self.cheeses[:] + +# Test input +from cheesy import CheeseShop + +shop = CheeseShop() +print(shop.cheese) + +shop.cheese = "camembert" +print(shop.cheese) + +shop.cheese = "cheddar" +print(shop.cheese) + +del shop.cheese +print(shop.cheese) diff --git a/docs/examples/userguide/extension_types/dataclass.py b/docs/examples/userguide/extension_types/dataclass.py new file mode 100644 index 000000000..d8ed68666 --- /dev/null +++ b/docs/examples/userguide/extension_types/dataclass.py @@ -0,0 +1,21 @@ +import cython +try: + import typing + import dataclasses +except ImportError: + pass # The modules don't actually have to exists for Cython to use them as annotations + +@cython.dataclasses.dataclass +@cython.cclass +class MyDataclass: + # fields can be declared using annotations + a: cython.int = 0 + b: double = cython.dataclasses.field(default_factory = lambda: 10, repr=False) + + + c: str = 'hello' + + + # typing.InitVar and typing.ClassVar also work + d: dataclasses.InitVar[double] = 5 + e: typing.ClassVar[list] = [] diff --git a/docs/examples/userguide/extension_types/dataclass.pyx b/docs/examples/userguide/extension_types/dataclass.pyx new file mode 100644 index 000000000..b03d5f7b1 --- /dev/null +++ b/docs/examples/userguide/extension_types/dataclass.pyx @@ -0,0 +1,21 @@ +cimport cython +try: + import typing + import dataclasses +except ImportError: + pass # The modules don't actually have to exists for Cython to use them as annotations + + +@cython.dataclasses.dataclass +cdef class MyDataclass: + # fields can be declared using annotations + a: cython.int = 0 + b: double = cython.dataclasses.field(default_factory = lambda: 10, repr=False) + + # fields can also be declared using `cdef`: + cdef str c + c = "hello" # assignment of default value on a separate line + + # typing.InitVar and typing.ClassVar also work + d: dataclasses.InitVar[cython.double] = 5 + e: typing.ClassVar[list] = [] diff --git a/docs/examples/userguide/extension_types/dict_animal.py b/docs/examples/userguide/extension_types/dict_animal.py new file mode 100644 index 000000000..a36dd3f89 --- /dev/null +++ b/docs/examples/userguide/extension_types/dict_animal.py @@ -0,0 +1,12 @@ +@cython.cclass +class Animal: + + number_of_legs: cython.int + __dict__: dict + + def __cinit__(self, number_of_legs: cython.int): + self.number_of_legs = number_of_legs + + +dog = Animal(4) +dog.has_tail = True diff --git a/docs/examples/userguide/extension_types/dict_animal.pyx b/docs/examples/userguide/extension_types/dict_animal.pyx index ab66900fe..575b835e9 100644 --- a/docs/examples/userguide/extension_types/dict_animal.pyx +++ b/docs/examples/userguide/extension_types/dict_animal.pyx @@ -1,11 +1,12 @@ -cdef class Animal:
-
- cdef int number_of_legs
- cdef dict __dict__
-
- def __cinit__(self, int number_of_legs):
- self.number_of_legs = number_of_legs
-
-
-dog = Animal(4)
-dog.has_tail = True
+ +cdef class Animal: + + cdef int number_of_legs + cdef dict __dict__ + + def __init__(self, int number_of_legs): + self.number_of_legs = number_of_legs + + +dog = Animal(4) +dog.has_tail = True diff --git a/docs/examples/userguide/extension_types/extendable_animal.py b/docs/examples/userguide/extension_types/extendable_animal.py new file mode 100644 index 000000000..2eef69460 --- /dev/null +++ b/docs/examples/userguide/extension_types/extendable_animal.py @@ -0,0 +1,15 @@ +@cython.cclass +class Animal: + + number_of_legs: cython.int + + def __cinit__(self, number_of_legs: cython.int): + self.number_of_legs = number_of_legs + + +class ExtendableAnimal(Animal): # Note that we use class, not cdef class + pass + + +dog = ExtendableAnimal(4) +dog.has_tail = True diff --git a/docs/examples/userguide/extension_types/extendable_animal.pyx b/docs/examples/userguide/extension_types/extendable_animal.pyx index fe53218b5..2ec165421 100644 --- a/docs/examples/userguide/extension_types/extendable_animal.pyx +++ b/docs/examples/userguide/extension_types/extendable_animal.pyx @@ -1,14 +1,15 @@ -cdef class Animal:
-
- cdef int number_of_legs
-
- def __cinit__(self, int number_of_legs):
- self.number_of_legs = number_of_legs
-
-
-class ExtendableAnimal(Animal): # Note that we use class, not cdef class
- pass
-
-
-dog = ExtendableAnimal(4)
-dog.has_tail = True
\ No newline at end of file + +cdef class Animal: + + cdef int number_of_legs + + def __init__(self, int number_of_legs): + self.number_of_legs = number_of_legs + + +class ExtendableAnimal(Animal): # Note that we use class, not cdef class + pass + + +dog = ExtendableAnimal(4) +dog.has_tail = True diff --git a/docs/examples/userguide/extension_types/my_module.pyx b/docs/examples/userguide/extension_types/my_module.pyx index 6ceb057ca..fb0701c12 100644 --- a/docs/examples/userguide/extension_types/my_module.pyx +++ b/docs/examples/userguide/extension_types/my_module.pyx @@ -1,11 +1,11 @@ -from __future__ import print_function
-
-cdef class Shrubbery:
-
- def __init__(self, w, h):
- self.width = w
- self.height = h
-
- def describe(self):
- print("This shrubbery is", self.width,
- "by", self.height, "cubits.")
+from __future__ import print_function + +cdef class Shrubbery: + + def __init__(self, w, h): + self.width = w + self.height = h + + def describe(self): + print("This shrubbery is", self.width, + "by", self.height, "cubits.") diff --git a/docs/examples/userguide/extension_types/owned_pointer.py b/docs/examples/userguide/extension_types/owned_pointer.py new file mode 100644 index 000000000..1c235a883 --- /dev/null +++ b/docs/examples/userguide/extension_types/owned_pointer.py @@ -0,0 +1,17 @@ +import cython +from cython.cimports.libc.stdlib import free + +@cython.cclass +class OwnedPointer: + ptr: cython.pointer(cython.void) + + def __dealloc__(self): + if self.ptr is not cython.NULL: + free(self.ptr) + + @staticmethod + @cython.cfunc + def create(ptr: cython.pointer(cython.void)): + p = OwnedPointer() + p.ptr = ptr + return p diff --git a/docs/examples/userguide/extension_types/owned_pointer.pyx b/docs/examples/userguide/extension_types/owned_pointer.pyx new file mode 100644 index 000000000..98b61d91c --- /dev/null +++ b/docs/examples/userguide/extension_types/owned_pointer.pyx @@ -0,0 +1,17 @@ + +from libc.stdlib cimport free + + +cdef class OwnedPointer: + cdef void* ptr + + def __dealloc__(self): + if self.ptr is not NULL: + free(self.ptr) + + + @staticmethod + cdef create(void* ptr): + p = OwnedPointer() + p.ptr = ptr + return p diff --git a/docs/examples/userguide/extension_types/penguin.py b/docs/examples/userguide/extension_types/penguin.py new file mode 100644 index 000000000..6db8eba16 --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin.py @@ -0,0 +1,14 @@ +import cython + +@cython.cclass +class Penguin: + food: object + + def __cinit__(self, food): + self.food = food + + def __init__(self, food): + print("eating!") + +normal_penguin = Penguin('fish') +fast_penguin = Penguin.__new__(Penguin, 'wheat') # note: not calling __init__() ! diff --git a/docs/examples/userguide/extension_types/penguin.pyx b/docs/examples/userguide/extension_types/penguin.pyx new file mode 100644 index 000000000..b890c9ffd --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin.pyx @@ -0,0 +1,14 @@ + + + +cdef class Penguin: + cdef object food + + def __cinit__(self, food): + self.food = food + + def __init__(self, food): + print("eating!") + +normal_penguin = Penguin('fish') +fast_penguin = Penguin.__new__(Penguin, 'wheat') # note: not calling __init__() ! diff --git a/docs/examples/userguide/extension_types/penguin2.py b/docs/examples/userguide/extension_types/penguin2.py new file mode 100644 index 000000000..063563d16 --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin2.py @@ -0,0 +1,12 @@ +import cython + +@cython.freelist(8) +@cython.cclass +class Penguin: + food: object + def __cinit__(self, food): + self.food = food + +penguin = Penguin('fish 1') +penguin = None +penguin = Penguin('fish 2') # does not need to allocate memory! diff --git a/docs/examples/userguide/extension_types/penguin2.pyx b/docs/examples/userguide/extension_types/penguin2.pyx new file mode 100644 index 000000000..726aeef8e --- /dev/null +++ b/docs/examples/userguide/extension_types/penguin2.pyx @@ -0,0 +1,12 @@ +cimport cython + + +@cython.freelist(8) +cdef class Penguin: + cdef object food + def __cinit__(self, food): + self.food = food + +penguin = Penguin('fish 1') +penguin = None +penguin = Penguin('fish 2') # does not need to allocate memory! diff --git a/docs/examples/userguide/extension_types/pets.py b/docs/examples/userguide/extension_types/pets.py new file mode 100644 index 000000000..fc6497cb0 --- /dev/null +++ b/docs/examples/userguide/extension_types/pets.py @@ -0,0 +1,22 @@ +import cython + +@cython.cclass +class Parrot: + + @cython.cfunc + def describe(self) -> cython.void: + print("This parrot is resting.") + +@cython.cclass +class Norwegian(Parrot): + + @cython.cfunc + def describe(self) -> cython.void: + Parrot.describe(self) + print("Lovely plumage!") + +cython.declare(p1=Parrot, p2=Parrot) +p1 = Parrot() +p2 = Norwegian() +print("p2:") +p2.describe() diff --git a/docs/examples/userguide/extension_types/pets.pyx b/docs/examples/userguide/extension_types/pets.pyx new file mode 100644 index 000000000..bb06e059d --- /dev/null +++ b/docs/examples/userguide/extension_types/pets.pyx @@ -0,0 +1,22 @@ + + +cdef class Parrot: + + + + cdef void describe(self): + print("This parrot is resting.") + + +cdef class Norwegian(Parrot): + + + cdef void describe(self): + Parrot.describe(self) + print("Lovely plumage!") + +cdef Parrot p1, p2 +p1 = Parrot() +p2 = Norwegian() +print("p2:") +p2.describe() diff --git a/docs/examples/userguide/extension_types/python_access.py b/docs/examples/userguide/extension_types/python_access.py new file mode 100644 index 000000000..27478f50c --- /dev/null +++ b/docs/examples/userguide/extension_types/python_access.py @@ -0,0 +1,7 @@ +import cython + +@cython.cclass +class Shrubbery: + width = cython.declare(cython.int, visibility='public') + height = cython.declare(cython.int, visibility='public') + depth = cython.declare(cython.float, visibility='readonly') diff --git a/docs/examples/userguide/extension_types/python_access.pyx b/docs/examples/userguide/extension_types/python_access.pyx index 13e19091e..db11de63c 100644 --- a/docs/examples/userguide/extension_types/python_access.pyx +++ b/docs/examples/userguide/extension_types/python_access.pyx @@ -1,3 +1,7 @@ -cdef class Shrubbery:
- cdef public int width, height
- cdef readonly float depth
+ + + +cdef class Shrubbery: + cdef public int width, height + + cdef readonly float depth diff --git a/docs/examples/userguide/extension_types/shrubbery.py b/docs/examples/userguide/extension_types/shrubbery.py new file mode 100644 index 000000000..0e624a1d2 --- /dev/null +++ b/docs/examples/userguide/extension_types/shrubbery.py @@ -0,0 +1,12 @@ +@cython.cclass +class Shrubbery: + width: cython.int + height: cython.int + + def __init__(self, w, h): + self.width = w + self.height = h + + def describe(self): + print("This shrubbery is", self.width, + "by", self.height, "cubits.") diff --git a/docs/examples/userguide/extension_types/shrubbery.pyx b/docs/examples/userguide/extension_types/shrubbery.pyx index 9d2a5481a..8c4e58776 100644 --- a/docs/examples/userguide/extension_types/shrubbery.pyx +++ b/docs/examples/userguide/extension_types/shrubbery.pyx @@ -1,12 +1,12 @@ -from __future__ import print_function
-
-cdef class Shrubbery:
- cdef int width, height
-
- def __init__(self, w, h):
- self.width = w
- self.height = h
-
- def describe(self):
- print("This shrubbery is", self.width,
- "by", self.height, "cubits.")
+from __future__ import print_function +cdef class Shrubbery: + cdef int width + cdef int height + + def __init__(self, w, h): + self.width = w + self.height = h + + def describe(self): + print("This shrubbery is", self.width, + "by", self.height, "cubits.") diff --git a/docs/examples/userguide/extension_types/shrubbery_2.py b/docs/examples/userguide/extension_types/shrubbery_2.py new file mode 100644 index 000000000..d6b722500 --- /dev/null +++ b/docs/examples/userguide/extension_types/shrubbery_2.py @@ -0,0 +1,10 @@ +import cython +from cython.cimports.my_module import Shrubbery + +@cython.cfunc +def another_shrubbery(sh1: Shrubbery) -> Shrubbery: + sh2: Shrubbery + sh2 = Shrubbery() + sh2.width = sh1.width + sh2.height = sh1.height + return sh2 diff --git a/docs/examples/userguide/extension_types/shrubbery_2.pyx b/docs/examples/userguide/extension_types/shrubbery_2.pyx index e0d8c45b5..4a7782735 100644 --- a/docs/examples/userguide/extension_types/shrubbery_2.pyx +++ b/docs/examples/userguide/extension_types/shrubbery_2.pyx @@ -1,8 +1,10 @@ -from my_module cimport Shrubbery
-
-cdef Shrubbery another_shrubbery(Shrubbery sh1):
- cdef Shrubbery sh2
- sh2 = Shrubbery()
- sh2.width = sh1.width
- sh2.height = sh1.height
- return sh2
+ +from my_module cimport Shrubbery + + +cdef Shrubbery another_shrubbery(Shrubbery sh1): + cdef Shrubbery sh2 + sh2 = Shrubbery() + sh2.width = sh1.width + sh2.height = sh1.height + return sh2 diff --git a/docs/examples/userguide/extension_types/widen_shrubbery.py b/docs/examples/userguide/extension_types/widen_shrubbery.py new file mode 100644 index 000000000..f69f4dc96 --- /dev/null +++ b/docs/examples/userguide/extension_types/widen_shrubbery.py @@ -0,0 +1,6 @@ +import cython +from cython.cimports.my_module import Shrubbery + +@cython.cfunc +def widen_shrubbery(sh: Shrubbery, extra_width): + sh.width = sh.width + extra_width diff --git a/docs/examples/userguide/extension_types/widen_shrubbery.pyx b/docs/examples/userguide/extension_types/widen_shrubbery.pyx index aff3bd116..c6f58f00c 100644 --- a/docs/examples/userguide/extension_types/widen_shrubbery.pyx +++ b/docs/examples/userguide/extension_types/widen_shrubbery.pyx @@ -1,4 +1,6 @@ -from my_module cimport Shrubbery
-
-cdef widen_shrubbery(Shrubbery sh, extra_width):
- sh.width = sh.width + extra_width
+ +from my_module cimport Shrubbery + + +cdef widen_shrubbery(Shrubbery sh, extra_width): + sh.width = sh.width + extra_width diff --git a/docs/examples/userguide/extension_types/wrapper_class.py b/docs/examples/userguide/extension_types/wrapper_class.py new file mode 100644 index 000000000..b625ffebd --- /dev/null +++ b/docs/examples/userguide/extension_types/wrapper_class.py @@ -0,0 +1,65 @@ +import cython +from cython.cimports.libc.stdlib import malloc, free + +# Example C struct +my_c_struct = cython.struct( + a = cython.int, + b = cython.int, +) + +@cython.cclass +class WrapperClass: + """A wrapper class for a C/C++ data structure""" + _ptr: cython.pointer(my_c_struct) + ptr_owner: cython.bint + + def __cinit__(self): + self.ptr_owner = False + + def __dealloc__(self): + # De-allocate if not null and flag is set + if self._ptr is not cython.NULL and self.ptr_owner is True: + free(self._ptr) + self._ptr = cython.NULL + + def __init__(self): + # Prevent accidental instantiation from normal Python code + # since we cannot pass a struct pointer into a Python constructor. + raise TypeError("This class cannot be instantiated directly.") + + # Extension class properties + @property + def a(self): + return self._ptr.a if self._ptr is not cython.NULL else None + + @property + def b(self): + return self._ptr.b if self._ptr is not cython.NULL else None + + @staticmethod + @cython.cfunc + def from_ptr(_ptr: cython.pointer(my_c_struct), owner: cython.bint=False) -> WrapperClass: + """Factory function to create WrapperClass objects from + given my_c_struct pointer. + + Setting ``owner`` flag to ``True`` causes + the extension type to ``free`` the structure pointed to by ``_ptr`` + when the wrapper object is deallocated.""" + # Fast call to __new__() that bypasses the __init__() constructor. + wrapper: WrapperClass = WrapperClass.__new__(WrapperClass) + wrapper._ptr = _ptr + wrapper.ptr_owner = owner + return wrapper + + @staticmethod + @cython.cfunc + def new_struct() -> WrapperClass: + """Factory function to create WrapperClass objects with + newly allocated my_c_struct""" + _ptr: cython.pointer(my_c_struct) = cython.cast( + cython.pointer(my_c_struct), malloc(cython.sizeof(my_c_struct))) + if _ptr is cython.NULL: + raise MemoryError + _ptr.a = 0 + _ptr.b = 0 + return WrapperClass.from_ptr(_ptr, owner=True) diff --git a/docs/examples/userguide/extension_types/wrapper_class.pyx b/docs/examples/userguide/extension_types/wrapper_class.pyx new file mode 100644 index 000000000..e2a0c3ff2 --- /dev/null +++ b/docs/examples/userguide/extension_types/wrapper_class.pyx @@ -0,0 +1,65 @@ + +from libc.stdlib cimport malloc, free + +# Example C struct +ctypedef struct my_c_struct: + int a + int b + + + +cdef class WrapperClass: + """A wrapper class for a C/C++ data structure""" + cdef my_c_struct *_ptr + cdef bint ptr_owner + + def __cinit__(self): + self.ptr_owner = False + + def __dealloc__(self): + # De-allocate if not null and flag is set + if self._ptr is not NULL and self.ptr_owner is True: + free(self._ptr) + self._ptr = NULL + + def __init__(self): + # Prevent accidental instantiation from normal Python code + # since we cannot pass a struct pointer into a Python constructor. + raise TypeError("This class cannot be instantiated directly.") + + # Extension class properties + @property + def a(self): + return self._ptr.a if self._ptr is not NULL else None + + @property + def b(self): + return self._ptr.b if self._ptr is not NULL else None + + + @staticmethod + cdef WrapperClass from_ptr(my_c_struct *_ptr, bint owner=False): + """Factory function to create WrapperClass objects from + given my_c_struct pointer. + + Setting ``owner`` flag to ``True`` causes + the extension type to ``free`` the structure pointed to by ``_ptr`` + when the wrapper object is deallocated.""" + # Fast call to __new__() that bypasses the __init__() constructor. + cdef WrapperClass wrapper = WrapperClass.__new__(WrapperClass) + wrapper._ptr = _ptr + wrapper.ptr_owner = owner + return wrapper + + + @staticmethod + cdef WrapperClass new_struct(): + """Factory function to create WrapperClass objects with + newly allocated my_c_struct""" + cdef my_c_struct *_ptr = <my_c_struct *>malloc(sizeof(my_c_struct)) + + if _ptr is NULL: + raise MemoryError + _ptr.a = 0 + _ptr.b = 0 + return WrapperClass.from_ptr(_ptr, owner=True) diff --git a/docs/examples/userguide/external_C_code/delorean.pyx b/docs/examples/userguide/external_C_code/delorean.pyx index 52c713616..9c6af9f87 100644 --- a/docs/examples/userguide/external_C_code/delorean.pyx +++ b/docs/examples/userguide/external_C_code/delorean.pyx @@ -1,9 +1,9 @@ -# delorean.pyx
-
-cdef public struct Vehicle:
- int speed
- float power
-
-cdef api void activate(Vehicle *v):
- if v.speed >= 88 and v.power >= 1.21:
- print("Time travel achieved")
\ No newline at end of file +# delorean.pyx + +cdef public struct Vehicle: + int speed + float power + +cdef api void activate(Vehicle *v) except *: + if v.speed >= 88 and v.power >= 1.21: + print("Time travel achieved") diff --git a/docs/examples/userguide/external_C_code/marty.c b/docs/examples/userguide/external_C_code/marty.c index 8096ab19a..d7f5117f7 100644 --- a/docs/examples/userguide/external_C_code/marty.c +++ b/docs/examples/userguide/external_C_code/marty.c @@ -1,13 +1,14 @@ -# marty.c
-#include "delorean_api.h"
-
-Vehicle car;
-
-int main(int argc, char *argv[]) {
- Py_Initialize();
- import_delorean();
- car.speed = atoi(argv[1]);
- car.power = atof(argv[2]);
- activate(&car);
- Py_Finalize();
-}
+# marty.c +#include "delorean_api.h" + +Vehicle car; + +int main(int argc, char *argv[]) { + Py_Initialize(); + import_delorean(); + car.speed = atoi(argv[1]); + car.power = atof(argv[2]); + activate(&car); + /* Error handling left out - call PyErr_Occurred() to test for Python exceptions. */ + Py_Finalize(); +} diff --git a/docs/examples/userguide/external_C_code/platform_adaptation.pyx b/docs/examples/userguide/external_C_code/platform_adaptation.pyx new file mode 100644 index 000000000..0beece8f4 --- /dev/null +++ b/docs/examples/userguide/external_C_code/platform_adaptation.pyx @@ -0,0 +1,14 @@ +cdef extern from *: + """ + #if defined(_WIN32) || defined(MS_WINDOWS) || defined(_MSC_VER) + #include "stdlib.h" + #define myapp_sleep(m) _sleep(m) + #else + #include <unistd.h> + #define myapp_sleep(m) ((void) usleep((m) * 1000)) + #endif + """ + # using "myapp_" prefix in the C code to prevent C naming conflicts + void msleep "myapp_sleep"(int milliseconds) nogil + +msleep(milliseconds=1) diff --git a/docs/examples/userguide/external_C_code/struct_field_adaptation.h b/docs/examples/userguide/external_C_code/struct_field_adaptation.h new file mode 100644 index 000000000..ca55460f4 --- /dev/null +++ b/docs/examples/userguide/external_C_code/struct_field_adaptation.h @@ -0,0 +1,13 @@ +typedef struct { + int field1; + int field2; + int newly_added_field; +} StructType; + +static StructType global_struct; + +static StructType *get_struct_ptr() { + return &global_struct; +} + +#define C_LIB_VERSION 20 diff --git a/docs/examples/userguide/external_C_code/struct_field_adaptation.pyx b/docs/examples/userguide/external_C_code/struct_field_adaptation.pyx new file mode 100644 index 000000000..cff6bbdc2 --- /dev/null +++ b/docs/examples/userguide/external_C_code/struct_field_adaptation.pyx @@ -0,0 +1,31 @@ +cdef extern from "struct_field_adaptation.h": + """ + #define HAS_NEWLY_ADDED_FIELD (C_LIB_VERSION >= 20) + + #if HAS_NEWLY_ADDED_FIELD + #define _mylib_get_newly_added_field(a_struct_ptr) ((a_struct_ptr)->newly_added_field) + #define _mylib_set_newly_added_field(a_struct_ptr, value) ((a_struct_ptr)->newly_added_field) = (value) + #else + #define _mylib_get_newly_added_field(a_struct_ptr) (0) + #define _mylib_set_newly_added_field(a_struct_ptr, value) ((void) (value)) + #endif + """ + + # Normal declarations provided by the C header file: + ctypedef struct StructType: + int field1 + int field2 + + StructType *get_struct_ptr() + + # Special declarations conditionally provided above: + bint HAS_NEWLY_ADDED_FIELD + int get_newly_added_field "_mylib_get_newly_added_field" (StructType *struct_ptr) + void set_newly_added_field "_mylib_set_newly_added_field" (StructType *struct_ptr, int value) + + +cdef StructType *some_struct_ptr = get_struct_ptr() + +print(some_struct_ptr.field1) +if HAS_NEWLY_ADDED_FIELD: + print(get_newly_added_field(some_struct_ptr)) diff --git a/docs/examples/userguide/external_C_code/c_code_docstring.pyx b/docs/examples/userguide/external_C_code/verbatim_c_code.pyx index 430e89c48..fb1937166 100644 --- a/docs/examples/userguide/external_C_code/c_code_docstring.pyx +++ b/docs/examples/userguide/external_C_code/verbatim_c_code.pyx @@ -1,9 +1,9 @@ -cdef extern from *:
- """
- /* This is C code which will be put
- * in the .c file output by Cython */
- static long square(long x) {return x * x;}
- #define assign(x, y) ((x) = (y))
- """
- long square(long x)
- void assign(long& x, long y)
+cdef extern from *: + """ + /* This is C code which will be put + * in the .c file output by Cython */ + static long square(long x) {return x * x;} + #define assign(x, y) ((x) = (y)) + """ + long square(long x) + void assign(long& x, long y) diff --git a/docs/examples/userguide/fusedtypes/char_or_float.py b/docs/examples/userguide/fusedtypes/char_or_float.py new file mode 100644 index 000000000..4930bf065 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/char_or_float.py @@ -0,0 +1,17 @@ +from __future__ import print_function + +char_or_float = cython.fused_type(cython.char, cython.float) + + + +@cython.ccall +def plus_one(var: char_or_float) -> char_or_float: + return var + 1 + + +def show_me(): + + a: cython.char = 127 + b: cython.float = 127 + print('char', plus_one(a)) + print('float', plus_one(b)) diff --git a/docs/examples/userguide/fusedtypes/char_or_float.pyx b/docs/examples/userguide/fusedtypes/char_or_float.pyx index 6db746831..5a525431f 100644 --- a/docs/examples/userguide/fusedtypes/char_or_float.pyx +++ b/docs/examples/userguide/fusedtypes/char_or_float.pyx @@ -1,17 +1,17 @@ -from __future__ import print_function
-
-ctypedef fused char_or_float:
- char
- float
-
-
-cpdef char_or_float plus_one(char_or_float var):
- return var + 1
-
-
-def show_me():
- cdef:
- char a = 127
- float b = 127
- print('char', plus_one(a))
- print('float', plus_one(b))
+from __future__ import print_function + +ctypedef fused char_or_float: + char + float + + +cpdef char_or_float plus_one(char_or_float var): + return var + 1 + + +def show_me(): + cdef: + char a = 127 + float b = 127 + print('char', plus_one(a)) + print('float', plus_one(b)) diff --git a/docs/examples/userguide/fusedtypes/conditional_gil.pyx b/docs/examples/userguide/fusedtypes/conditional_gil.pyx new file mode 100644 index 000000000..473132f2e --- /dev/null +++ b/docs/examples/userguide/fusedtypes/conditional_gil.pyx @@ -0,0 +1,15 @@ +cimport cython + +ctypedef fused double_or_object: + double + object + +def increment(double_or_object x): + with nogil(double_or_object is not object): + # Same code handles both cython.double (GIL is released) + # and python object (GIL is not released). + x = x + 1 + return x + +increment(5.0) # GIL is released during increment +increment(5) # GIL is acquired during increment diff --git a/docs/examples/userguide/fusedtypes/indexing.py b/docs/examples/userguide/fusedtypes/indexing.py new file mode 100644 index 000000000..054f6a742 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/indexing.py @@ -0,0 +1,25 @@ +import cython + +fused_type1 = cython.fused_type(cython.double, cython.float) + + + +fused_type2 = cython.fused_type(cython.double, cython.float) + + +@cython.cfunc +def cfunc(arg1: fused_type1, arg2: fused_type1): + print("cfunc called:", cython.typeof(arg1), arg1, cython.typeof(arg2), arg2) + +@cython.ccall +def cpfunc(a: fused_type1, b: fused_type2): + print("cpfunc called:", cython.typeof(a), a, cython.typeof(b), b) + +def func(a: fused_type1, b: fused_type2): + print("func called:", cython.typeof(a), a, cython.typeof(b), b) + +# called from Cython space +cfunc[cython.double](5.0, 1.0) +cpfunc[cython.float, cython.double](1.0, 2.0) +# Indexing def functions in Cython code requires string names +func["float", "double"](1.0, 2.0) diff --git a/docs/examples/userguide/fusedtypes/indexing.pyx b/docs/examples/userguide/fusedtypes/indexing.pyx new file mode 100644 index 000000000..16c7395f0 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/indexing.pyx @@ -0,0 +1,25 @@ +cimport cython + +ctypedef fused fused_type1: + double + float + +ctypedef fused fused_type2: + double + float + +cdef cfunc(fused_type1 arg1, fused_type1 arg2): + print("cfunc called:", cython.typeof(arg1), arg1, cython.typeof(arg2), arg2) + + +cpdef cpfunc(fused_type1 a, fused_type2 b): + print("cpfunc called:", cython.typeof(a), a, cython.typeof(b), b) + +def func(fused_type1 a, fused_type2 b): + print("func called:", cython.typeof(a), a, cython.typeof(b), b) + +# called from Cython space +cfunc[double](5.0, 1.0) +cpfunc[float, double](1.0, 2.0) +# Indexing def function in Cython code requires string names +func["float", "double"](1.0, 2.0) diff --git a/docs/examples/userguide/fusedtypes/pointer.py b/docs/examples/userguide/fusedtypes/pointer.py new file mode 100644 index 000000000..043074c79 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/pointer.py @@ -0,0 +1,13 @@ +my_fused_type = cython.fused_type(cython.int, cython.float) + + +@cython.cfunc +def func(a: cython.pointer(my_fused_type)): + print(a[0]) + +def main(): + a: cython.int = 3 + b: cython.float = 5.0 + + func(cython.address(a)) + func(cython.address(b)) diff --git a/docs/examples/userguide/fusedtypes/pointer.pyx b/docs/examples/userguide/fusedtypes/pointer.pyx new file mode 100644 index 000000000..ad7758c16 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/pointer.pyx @@ -0,0 +1,13 @@ +ctypedef fused my_fused_type: + int + double + +cdef func(my_fused_type *a): + print(a[0]) + + +cdef int b = 3 +cdef double c = 3.0 + +func(&b) +func(&c) diff --git a/docs/examples/userguide/fusedtypes/type_checking.py b/docs/examples/userguide/fusedtypes/type_checking.py new file mode 100644 index 000000000..bffe4b328 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/type_checking.py @@ -0,0 +1,28 @@ +bunch_of_types = cython.fused_type(bytes, cython.int, cython.float) + + + + + + +string_t = cython.fused_type(cython.p_char, bytes, unicode) + + + +@cython.cfunc +def myfunc(i: cython.integral, s: bunch_of_types) -> cython.integral: + # Only one of these branches will be compiled for each specialization! + if cython.integral is int: + print('i is an int') + elif cython.integral is long: + print('i is a long') + else: + print('i is a short') + + if bunch_of_types in string_t: + print("s is a string!") + return i * 2 + +myfunc(cython.cast(cython.int, 5), b'm') # will print "i is an int" and "s is a string" +myfunc(cython.cast(cython.long, 5), 3) # will print "i is a long" +myfunc(cython.cast(cython.short, 5), 3) # will print "i is a short" diff --git a/docs/examples/userguide/fusedtypes/type_checking.pyx b/docs/examples/userguide/fusedtypes/type_checking.pyx new file mode 100644 index 000000000..7bd359739 --- /dev/null +++ b/docs/examples/userguide/fusedtypes/type_checking.pyx @@ -0,0 +1,28 @@ +cimport cython + +ctypedef fused bunch_of_types: + bytes + int + float + +ctypedef fused string_t: + cython.p_char + bytes + unicode + +cdef cython.integral myfunc(cython.integral i, bunch_of_types s): + # Only one of these branches will be compiled for each specialization! + if cython.integral is int: + print('i is int') + elif cython.integral is long: + print('i is long') + else: + print('i is short') + + if bunch_of_types in string_t: + print("s is a string!") + return i * 2 + +myfunc(<int> 5, b'm') # will print "i is an int" and "s is a string" +myfunc(<long> 5, 3) # will print "i is a long" +myfunc(<short> 5, 3) # will print "i is a short" diff --git a/docs/examples/userguide/language_basics/casting_python.pxd b/docs/examples/userguide/language_basics/casting_python.pxd new file mode 100644 index 000000000..fa3d46030 --- /dev/null +++ b/docs/examples/userguide/language_basics/casting_python.pxd @@ -0,0 +1,2 @@ +cdef extern from *: + ctypedef Py_ssize_t Py_intptr_t diff --git a/docs/examples/userguide/language_basics/casting_python.py b/docs/examples/userguide/language_basics/casting_python.py new file mode 100644 index 000000000..1c02c461c --- /dev/null +++ b/docs/examples/userguide/language_basics/casting_python.py @@ -0,0 +1,22 @@ +from cython.cimports.cpython.ref import PyObject + +def main(): + + python_string = "foo" + + # Note that the variables below are automatically inferred + # as the correct pointer type that is assigned to them. + # They do not need to be typed explicitly. + + ptr = cython.cast(cython.p_void, python_string) + adress_in_c = cython.cast(Py_intptr_t, ptr) + address_from_void = adress_in_c # address_from_void is a python int + + ptr2 = cython.cast(cython.pointer(PyObject), python_string) + address_in_c2 = cython.cast(Py_intptr_t, ptr2) + address_from_PyObject = address_in_c2 # address_from_PyObject is a python int + + assert address_from_void == address_from_PyObject == id(python_string) + + print(cython.cast(object, ptr)) # Prints "foo" + print(cython.cast(object, ptr2)) # prints "foo" diff --git a/docs/examples/userguide/language_basics/casting_python.pyx b/docs/examples/userguide/language_basics/casting_python.pyx index fe84acde2..4cc819ae3 100644 --- a/docs/examples/userguide/language_basics/casting_python.pyx +++ b/docs/examples/userguide/language_basics/casting_python.pyx @@ -1,19 +1,19 @@ -from cpython.ref cimport PyObject
-
-cdef extern from *:
- ctypedef Py_ssize_t Py_intptr_t
-
-python_string = "foo"
-
-cdef void* ptr = <void*>python_string
-cdef Py_intptr_t adress_in_c = <Py_intptr_t>ptr
-address_from_void = adress_in_c # address_from_void is a python int
-
-cdef PyObject* ptr2 = <PyObject*>python_string
-cdef Py_intptr_t address_in_c2 = <Py_intptr_t>ptr2
-address_from_PyObject = address_in_c2 # address_from_PyObject is a python int
-
-assert address_from_void == address_from_PyObject == id(python_string)
-
-print(<object>ptr) # Prints "foo"
-print(<object>ptr2) # prints "foo"
+from cpython.ref cimport PyObject + +cdef extern from *: + ctypedef Py_ssize_t Py_intptr_t + +python_string = "foo" + +cdef void* ptr = <void*>python_string +cdef Py_intptr_t adress_in_c = <Py_intptr_t>ptr +address_from_void = adress_in_c # address_from_void is a python int + +cdef PyObject* ptr2 = <PyObject*>python_string +cdef Py_intptr_t address_in_c2 = <Py_intptr_t>ptr2 +address_from_PyObject = address_in_c2 # address_from_PyObject is a python int + +assert address_from_void == address_from_PyObject == id(python_string) + +print(<object>ptr) # Prints "foo" +print(<object>ptr2) # prints "foo" diff --git a/docs/examples/userguide/language_basics/cdef_block.pyx b/docs/examples/userguide/language_basics/cdef_block.pyx index 4132aeee1..c0c303029 100644 --- a/docs/examples/userguide/language_basics/cdef_block.pyx +++ b/docs/examples/userguide/language_basics/cdef_block.pyx @@ -1,12 +1,12 @@ -from __future__ import print_function
-
-cdef:
- struct Spam:
- int tons
-
- int i
- float a
- Spam *p
-
- void f(Spam *s):
- print(s.tons, "Tons of spam")
+from __future__ import print_function + +cdef: + struct Spam: + int tons + + int i + float a + Spam *p + + void f(Spam *s) except *: + print(s.tons, "Tons of spam") diff --git a/docs/examples/userguide/language_basics/compile_time.pyx b/docs/examples/userguide/language_basics/compile_time.pyx index fcaf75f29..f302dd241 100644 --- a/docs/examples/userguide/language_basics/compile_time.pyx +++ b/docs/examples/userguide/language_basics/compile_time.pyx @@ -1,9 +1,9 @@ -from __future__ import print_function
-
-DEF FavouriteFood = u"spam"
-DEF ArraySize = 42
-DEF OtherArraySize = 2 * ArraySize + 17
-
-cdef int a1[ArraySize]
-cdef int a2[OtherArraySize]
-print("I like", FavouriteFood)
\ No newline at end of file +from __future__ import print_function + +DEF FavouriteFood = u"spam" +DEF ArraySize = 42 +DEF OtherArraySize = 2 * ArraySize + 17 + +cdef int[ArraySize] a1 +cdef int[OtherArraySize] a2 +print("I like", FavouriteFood) diff --git a/docs/examples/userguide/language_basics/struct_union_enum.pyx b/docs/examples/userguide/language_basics/enum.pyx index ccbc28d42..1b5f5d614 100644 --- a/docs/examples/userguide/language_basics/struct_union_enum.pyx +++ b/docs/examples/userguide/language_basics/enum.pyx @@ -1,16 +1,11 @@ -cdef struct Grail:
- int age
- float volume
-
-cdef union Food:
- char *spam
- float *eggs
-
-cdef enum CheeseType:
- cheddar, edam,
- camembert
-
-cdef enum CheeseState:
- hard = 1
- soft = 2
- runny = 3
+cdef enum CheeseType: + cheddar, edam, + camembert + +cdef enum CheeseState: + hard = 1 + soft = 2 + runny = 3 + +print(CheeseType.cheddar) +print(CheeseState.hard) diff --git a/docs/examples/userguide/language_basics/function_pointer.pyx b/docs/examples/userguide/language_basics/function_pointer.pyx new file mode 100644 index 000000000..b345c62b4 --- /dev/null +++ b/docs/examples/userguide/language_basics/function_pointer.pyx @@ -0,0 +1,8 @@ +cdef int(*ptr_add)(int, int) + +cdef int add(int a, int b): + return a + b + +ptr_add = add + +print(ptr_add(1, 3)) diff --git a/docs/examples/userguide/language_basics/function_pointer_struct.pyx b/docs/examples/userguide/language_basics/function_pointer_struct.pyx new file mode 100644 index 000000000..5ef618961 --- /dev/null +++ b/docs/examples/userguide/language_basics/function_pointer_struct.pyx @@ -0,0 +1,9 @@ +cdef struct Bar: + int sum(int a, int b) + +cdef int add(int a, int b): + return a + b + +cdef Bar bar = Bar(add) + +print(bar.sum(1, 2)) diff --git a/docs/examples/userguide/language_basics/kwargs_1.pyx b/docs/examples/userguide/language_basics/kwargs_1.pyx index e5e18c008..1117c967c 100644 --- a/docs/examples/userguide/language_basics/kwargs_1.pyx +++ b/docs/examples/userguide/language_basics/kwargs_1.pyx @@ -1,6 +1,6 @@ -def f(a, b, *args, c, d = 42, e, **kwds):
- ...
-
-
-# We cannot call f with less verbosity than this.
-foo = f(4, "bar", c=68, e=1.0)
+def f(a, b, *args, c, d = 42, e, **kwds): + ... + + +# We cannot call f with less verbosity than this. +foo = f(4, "bar", c=68, e=1.0) diff --git a/docs/examples/userguide/language_basics/kwargs_2.pyx b/docs/examples/userguide/language_basics/kwargs_2.pyx index a2c639ea6..902df694c 100644 --- a/docs/examples/userguide/language_basics/kwargs_2.pyx +++ b/docs/examples/userguide/language_basics/kwargs_2.pyx @@ -1,5 +1,5 @@ -def g(a, b, *, c, d):
- ...
-
-# We cannot call g with less verbosity than this.
-foo = g(4.0, "something", c=68, d="other")
+def g(a, b, *, c, d): + ... + +# We cannot call g with less verbosity than this. +foo = g(4.0, "something", c=68, d="other") diff --git a/docs/examples/userguide/language_basics/open_file.py b/docs/examples/userguide/language_basics/open_file.py new file mode 100644 index 000000000..ad3ae0374 --- /dev/null +++ b/docs/examples/userguide/language_basics/open_file.py @@ -0,0 +1,19 @@ +from cython.cimports.libc.stdio import FILE, fopen +from cython.cimports.libc.stdlib import malloc, free +from cython.cimports.cpython.exc import PyErr_SetFromErrnoWithFilenameObject + +def open_file(): + p = fopen("spam.txt", "r") # The type of "p" is "FILE*", as returned by fopen(). + + if p is cython.NULL: + PyErr_SetFromErrnoWithFilenameObject(OSError, "spam.txt") + ... + + +def allocating_memory(number=10): + # Note that the type of the variable "my_array" is automatically inferred from the assignment. + my_array = cython.cast(p_double, malloc(number * cython.sizeof(double))) + if not my_array: # same as 'is NULL' above + raise MemoryError() + ... + free(my_array) diff --git a/docs/examples/userguide/language_basics/open_file.pyx b/docs/examples/userguide/language_basics/open_file.pyx index 19eac104e..ad45fc8c4 100644 --- a/docs/examples/userguide/language_basics/open_file.pyx +++ b/docs/examples/userguide/language_basics/open_file.pyx @@ -1,18 +1,18 @@ -from libc.stdio cimport FILE, fopen
-from libc.stdlib cimport malloc, free
-from cpython.exc cimport PyErr_SetFromErrnoWithFilenameObject
-
-def open_file():
- cdef FILE* p
- p = fopen("spam.txt", "r")
- if p is NULL:
- PyErr_SetFromErrnoWithFilenameObject(OSError, "spam.txt")
- ...
-
-
-def allocating_memory(number=10):
- cdef double *my_array = <double *> malloc(number * sizeof(double))
- if not my_array: # same as 'is NULL' above
- raise MemoryError()
- ...
- free(my_array)
+from libc.stdio cimport FILE, fopen +from libc.stdlib cimport malloc, free +from cpython.exc cimport PyErr_SetFromErrnoWithFilenameObject + +def open_file(): + cdef FILE* p + p = fopen("spam.txt", "r") + if p is NULL: + PyErr_SetFromErrnoWithFilenameObject(OSError, "spam.txt") + ... + + +def allocating_memory(number=10): + cdef double *my_array = <double *> malloc(number * sizeof(double)) + if not my_array: # same as 'is NULL' above + raise MemoryError() + ... + free(my_array) diff --git a/docs/examples/userguide/language_basics/optional_subclassing.py b/docs/examples/userguide/language_basics/optional_subclassing.py new file mode 100644 index 000000000..480ae100b --- /dev/null +++ b/docs/examples/userguide/language_basics/optional_subclassing.py @@ -0,0 +1,19 @@ +from __future__ import print_function + +@cython.cclass +class A: + @cython.cfunc + def foo(self): + print("A") + +@cython.cclass +class B(A): + @cython.cfunc + def foo(self, x=None): + print("B", x) + +@cython.cclass +class C(B): + @cython.ccall + def foo(self, x=True, k:cython.int = 3): + print("C", x, k) diff --git a/docs/examples/userguide/language_basics/optional_subclassing.pyx b/docs/examples/userguide/language_basics/optional_subclassing.pyx index f655cadf3..b2a3d4dec 100644 --- a/docs/examples/userguide/language_basics/optional_subclassing.pyx +++ b/docs/examples/userguide/language_basics/optional_subclassing.pyx @@ -1,13 +1,19 @@ -from __future__ import print_function
-
-cdef class A:
- cdef foo(self):
- print("A")
-
-cdef class B(A):
- cdef foo(self, x=None):
- print("B", x)
-
-cdef class C(B):
- cpdef foo(self, x=True, int k=3):
- print("C", x, k)
+from __future__ import print_function + + +cdef class A: + + cdef foo(self): + print("A") + + +cdef class B(A): + + cdef foo(self, x=None): + print("B", x) + + +cdef class C(B): + + cpdef foo(self, x=True, int k=3): + print("C", x, k) diff --git a/docs/examples/userguide/language_basics/override.py b/docs/examples/userguide/language_basics/override.py new file mode 100644 index 000000000..f9e0be83f --- /dev/null +++ b/docs/examples/userguide/language_basics/override.py @@ -0,0 +1,17 @@ +from __future__ import print_function + +@cython.cclass +class A: + @cython.cfunc + def foo(self): + print("A") + +@cython.cclass +class B(A): + @cython.ccall + def foo(self): + print("B") + +class C(B): # NOTE: no cclass decorator + def foo(self): + print("C") diff --git a/docs/examples/userguide/language_basics/override.pyx b/docs/examples/userguide/language_basics/override.pyx index 873a7ec6e..1a7ceefb7 100644 --- a/docs/examples/userguide/language_basics/override.pyx +++ b/docs/examples/userguide/language_basics/override.pyx @@ -1,13 +1,17 @@ -from __future__ import print_function
-
-cdef class A:
- cdef foo(self):
- print("A")
-
-cdef class B(A):
- cpdef foo(self):
- print("B")
-
-class C(B): # NOTE: not cdef class
- def foo(self):
- print("C")
+from __future__ import print_function + + +cdef class A: + + cdef foo(self): + print("A") + + +cdef class B(A): + + cpdef foo(self): + print("B") + +class C(B): # NOTE: not cdef class + def foo(self): + print("C") diff --git a/docs/examples/userguide/language_basics/parameter_refcount.py b/docs/examples/userguide/language_basics/parameter_refcount.py new file mode 100644 index 000000000..2b25915ba --- /dev/null +++ b/docs/examples/userguide/language_basics/parameter_refcount.py @@ -0,0 +1,23 @@ +from __future__ import print_function + +from cython.cimports.cpython.ref import PyObject + +import sys + +python_dict = {"abc": 123} +python_dict_refcount = sys.getrefcount(python_dict) + +@cython.cfunc +def owned_reference(obj: object): + refcount = sys.getrefcount(python_dict) + print('Inside owned_reference: {refcount}'.format(refcount=refcount)) + +@cython.cfunc +def borrowed_reference(obj: cython.pointer(PyObject)): + refcount = obj.ob_refcnt + print('Inside borrowed_reference: {refcount}'.format(refcount=refcount)) + +def main(): + print('Initial refcount: {refcount}'.format(refcount=python_dict_refcount)) + owned_reference(python_dict) + borrowed_reference(cython.cast(cython.pointer(PyObject), python_dict)) diff --git a/docs/examples/userguide/language_basics/parameter_refcount.pyx b/docs/examples/userguide/language_basics/parameter_refcount.pyx new file mode 100644 index 000000000..6fe3ffadd --- /dev/null +++ b/docs/examples/userguide/language_basics/parameter_refcount.pyx @@ -0,0 +1,23 @@ +from __future__ import print_function + +from cpython.ref cimport PyObject + +import sys + +python_dict = {"abc": 123} +python_dict_refcount = sys.getrefcount(python_dict) + + +cdef owned_reference(object obj): + refcount = sys.getrefcount(python_dict) + print('Inside owned_reference: {refcount}'.format(refcount=refcount)) + + +cdef borrowed_reference(PyObject * obj): + refcount = obj.ob_refcnt + print('Inside borrowed_reference: {refcount}'.format(refcount=refcount)) + + +print('Initial refcount: {refcount}'.format(refcount=python_dict_refcount)) +owned_reference(python_dict) +borrowed_reference(<PyObject *>python_dict) diff --git a/docs/examples/userguide/language_basics/struct.py b/docs/examples/userguide/language_basics/struct.py new file mode 100644 index 000000000..32b6b252a --- /dev/null +++ b/docs/examples/userguide/language_basics/struct.py @@ -0,0 +1,7 @@ +Grail = cython.struct( + age=cython.int, + volume=cython.float) + +def main(): + grail: Grail = Grail(5, 3.0) + print(grail.age, grail.volume) diff --git a/docs/examples/userguide/language_basics/struct.pyx b/docs/examples/userguide/language_basics/struct.pyx new file mode 100644 index 000000000..3ef79172b --- /dev/null +++ b/docs/examples/userguide/language_basics/struct.pyx @@ -0,0 +1,7 @@ +cdef struct Grail: + int age + float volume + +def main(): + cdef Grail grail = Grail(5, 3.0) + print(grail.age, grail.volume) diff --git a/docs/examples/userguide/language_basics/union.py b/docs/examples/userguide/language_basics/union.py new file mode 100644 index 000000000..efcda358b --- /dev/null +++ b/docs/examples/userguide/language_basics/union.py @@ -0,0 +1,9 @@ +Food = cython.union( + spam=cython.p_char, + eggs=cython.p_float) + +def main(): + arr: cython.p_float = [1.0, 2.0] + spam: Food = Food(spam='b') + eggs: Food = Food(eggs=arr) + print(spam.spam, eggs.eggs[0]) diff --git a/docs/examples/userguide/language_basics/union.pyx b/docs/examples/userguide/language_basics/union.pyx new file mode 100644 index 000000000..e05f63fcc --- /dev/null +++ b/docs/examples/userguide/language_basics/union.pyx @@ -0,0 +1,9 @@ +cdef union Food: + char *spam + float *eggs + +def main(): + cdef float *arr = [1.0, 2.0] + cdef Food spam = Food(spam='b') + cdef Food eggs = Food(eggs=arr) + print(spam.spam, eggs.eggs[0]) diff --git a/docs/examples/userguide/memoryviews/add_one.pyx b/docs/examples/userguide/memoryviews/add_one.pyx index cbe65b069..7de7a1274 100644 --- a/docs/examples/userguide/memoryviews/add_one.pyx +++ b/docs/examples/userguide/memoryviews/add_one.pyx @@ -1,12 +1,12 @@ -import numpy as np
-
-def add_one(int[:,:] buf):
- for x in range(buf.shape[0]):
- for y in range(buf.shape[1]):
- buf[x, y] += 1
-
-# exporting_object must be a Python object
-# implementing the buffer interface, e.g. a numpy array.
-exporting_object = np.zeros((10, 20), dtype=np.intc)
-
-add_one(exporting_object)
+import numpy as np + +def add_one(int[:,:] buf): + for x in range(buf.shape[0]): + for y in range(buf.shape[1]): + buf[x, y] += 1 + +# exporting_object must be a Python object +# implementing the buffer interface, e.g. a numpy array. +exporting_object = np.zeros((10, 20), dtype=np.intc) + +add_one(exporting_object) diff --git a/docs/examples/userguide/memoryviews/copy.pyx b/docs/examples/userguide/memoryviews/copy.pyx index 9f000a3b4..9eb1307bf 100644 --- a/docs/examples/userguide/memoryviews/copy.pyx +++ b/docs/examples/userguide/memoryviews/copy.pyx @@ -1,12 +1,12 @@ -import numpy as np
-
-cdef int[:, :, :] to_view, from_view
-to_view = np.empty((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
-to_view[...] = from_view
-# or
-to_view[:] = from_view
-# or
-to_view[:, :, :] = from_view
+import numpy as np + +cdef int[:, :, :] to_view, from_view +to_view = np.empty((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 +to_view[...] = from_view +# or +to_view[:] = from_view +# or +to_view[:, :, :] = from_view diff --git a/docs/examples/userguide/memoryviews/custom_dtype.pyx b/docs/examples/userguide/memoryviews/custom_dtype.pyx new file mode 100644 index 000000000..d54d7bbc4 --- /dev/null +++ b/docs/examples/userguide/memoryviews/custom_dtype.pyx @@ -0,0 +1,26 @@ +import numpy as np + +CUSTOM_DTYPE = np.dtype([ + ('x', np.uint8), + ('y', np.float32), +]) + +a = np.zeros(100, dtype=CUSTOM_DTYPE) + +cdef packed struct custom_dtype_struct: + # The struct needs to be packed since by default numpy dtypes aren't + # aligned + unsigned char x + float y + +def sum(custom_dtype_struct [:] a): + + cdef: + unsigned char sum_x = 0 + float sum_y = 0. + + for i in range(a.shape[0]): + sum_x += a[i].x + sum_y += a[i].y + + return sum_x, sum_y diff --git a/docs/examples/userguide/memoryviews/memory_layout.pyx b/docs/examples/userguide/memoryviews/memory_layout.pyx index 5c2818dc0..8f9d8a23c 100644 --- a/docs/examples/userguide/memoryviews/memory_layout.pyx +++ b/docs/examples/userguide/memoryviews/memory_layout.pyx @@ -1,11 +1,11 @@ -from cython cimport view
-
-# direct access in both dimensions, strided in the first dimension, contiguous in the last
-cdef int[:, ::view.contiguous] a
-
-# contiguous list of pointers to contiguous lists of ints
-cdef int[::view.indirect_contiguous, ::1] b
-
-# direct or indirect in the first dimension, direct in the second dimension
-# strided in both dimensions
-cdef int[::view.generic, :] c
+from cython cimport view + +# direct access in both dimensions, strided in the first dimension, contiguous in the last +cdef int[:, ::view.contiguous] a + +# contiguous list of pointers to contiguous lists of ints +cdef int[::view.indirect_contiguous, ::1] b + +# direct or indirect in the first dimension, direct in the second dimension +# strided in both dimensions +cdef int[::view.generic, :] c diff --git a/docs/examples/userguide/memoryviews/memory_layout_2.pyx b/docs/examples/userguide/memoryviews/memory_layout_2.pyx index 1cb039dd4..71d2cceb2 100644 --- a/docs/examples/userguide/memoryviews/memory_layout_2.pyx +++ b/docs/examples/userguide/memoryviews/memory_layout_2.pyx @@ -1,6 +1,6 @@ -from cython cimport view
-
-# VALID
-cdef int[::view.indirect, ::1, :] a
-cdef int[::view.indirect, :, ::1] b
-cdef int[::view.indirect_contiguous, ::1, :] c
+from cython cimport view + +# VALID +cdef int[::view.indirect, ::1, :] a +cdef int[::view.indirect, :, ::1] b +cdef int[::view.indirect_contiguous, ::1, :] c diff --git a/docs/examples/userguide/memoryviews/memview_to_c.pyx b/docs/examples/userguide/memoryviews/memview_to_c.pyx index c5abc19ac..ad6190cc7 100644 --- a/docs/examples/userguide/memoryviews/memview_to_c.pyx +++ b/docs/examples/userguide/memoryviews/memview_to_c.pyx @@ -1,28 +1,28 @@ -cdef extern from "C_func_file.c":
- # C is include here so that it doesn't need to be compiled externally
- pass
-
-cdef extern from "C_func_file.h":
- void multiply_by_10_in_C(double *, unsigned int)
-
-import numpy as np
-
-def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array
-
- if not arr.flags['C_CONTIGUOUS']:
- arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array.
-
- cdef double[::1] arr_memview = arr
-
- multiply_by_10_in_C(&arr_memview[0], arr_memview.shape[0])
-
- return arr
-
-
-a = np.ones(5, dtype=np.double)
-print(multiply_by_10(a))
-
-b = np.ones(10, dtype=np.double)
-b = b[::2] # b is not contiguous.
-
-print(multiply_by_10(b)) # but our function still works as expected.
+cdef extern from "C_func_file.c": + # C is include here so that it doesn't need to be compiled externally + pass + +cdef extern from "C_func_file.h": + void multiply_by_10_in_C(double *, unsigned int) + +import numpy as np + +def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array + + if not arr.flags['C_CONTIGUOUS']: + arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array. + + cdef double[::1] arr_memview = arr + + multiply_by_10_in_C(&arr_memview[0], arr_memview.shape[0]) + + return arr + + +a = np.ones(5, dtype=np.double) +print(multiply_by_10(a)) + +b = np.ones(10, dtype=np.double) +b = b[::2] # b is not contiguous. + +print(multiply_by_10(b)) # but our function still works as expected. diff --git a/docs/examples/userguide/memoryviews/not_none.pyx b/docs/examples/userguide/memoryviews/not_none.pyx index ae3b6c936..f6c0fed8a 100644 --- a/docs/examples/userguide/memoryviews/not_none.pyx +++ b/docs/examples/userguide/memoryviews/not_none.pyx @@ -1,11 +1,11 @@ -import numpy as np
-
-def process_buffer(int[:,:] input_view not None,
- int[:,:] output_view=None):
-
- if output_view is None:
- # Creating a default view, e.g.
- output_view = np.empty_like(input_view)
-
- # process 'input_view' into 'output_view'
- return output_view
+import numpy as np + +def process_buffer(int[:,:] input_view not None, + int[:,:] output_view=None): + + if output_view is None: + # Creating a default view, e.g. + output_view = np.empty_like(input_view) + + # process 'input_view' into 'output_view' + return output_view diff --git a/docs/examples/userguide/memoryviews/np_flag_const.pyx b/docs/examples/userguide/memoryviews/np_flag_const.pyx index 03f0ea4a3..54eb3d338 100644 --- a/docs/examples/userguide/memoryviews/np_flag_const.pyx +++ b/docs/examples/userguide/memoryviews/np_flag_const.pyx @@ -1,7 +1,7 @@ -import numpy as np
-
-cdef const double[:] myslice # const item type => read-only view
-
-a = np.linspace(0, 10, num=50)
-a.setflags(write=False)
-myslice = a
+import numpy as np + +cdef const double[:] myslice # const item type => read-only view + +a = np.linspace(0, 10, num=50) +a.setflags(write=False) +myslice = a diff --git a/docs/examples/userguide/memoryviews/quickstart.pyx b/docs/examples/userguide/memoryviews/quickstart.pyx index 58335c0cf..a313859d9 100644 --- a/docs/examples/userguide/memoryviews/quickstart.pyx +++ b/docs/examples/userguide/memoryviews/quickstart.pyx @@ -6,7 +6,7 @@ narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3)) cdef int [:, :, :] narr_view = narr # Memoryview on a C array -cdef int carr[3][3][3] +cdef int[3][3][3] carr cdef int [:, :, :] carr_view = carr # Memoryview on a Cython array diff --git a/docs/examples/userguide/memoryviews/slicing.pyx b/docs/examples/userguide/memoryviews/slicing.pyx index a6134aae2..d7bd896e6 100644 --- a/docs/examples/userguide/memoryviews/slicing.pyx +++ b/docs/examples/userguide/memoryviews/slicing.pyx @@ -1,10 +1,10 @@ -import numpy as np
-
-exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20))
-
-cdef int[:, :, :] my_view = exporting_object
-
-# These are all equivalent
-my_view[10]
-my_view[10, :, :]
-my_view[10, ...]
+import numpy as np + +exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20)) + +cdef int[:, :, :] my_view = exporting_object + +# These are all equivalent +my_view[10] +my_view[10, :, :] +my_view[10, ...] diff --git a/docs/examples/userguide/memoryviews/transpose.pyx b/docs/examples/userguide/memoryviews/transpose.pyx index 7611529c2..8a53f7140 100644 --- a/docs/examples/userguide/memoryviews/transpose.pyx +++ b/docs/examples/userguide/memoryviews/transpose.pyx @@ -1,6 +1,6 @@ -import numpy as np
-
-array = np.arange(20, dtype=np.intc).reshape((2, 10))
-
-cdef int[:, ::1] c_contig = array
-cdef int[::1, :] f_contig = c_contig.T
+import numpy as np + +array = np.arange(20, dtype=np.intc).reshape((2, 10)) + +cdef int[:, ::1] c_contig = array +cdef int[::1, :] f_contig = c_contig.T diff --git a/docs/examples/userguide/memoryviews/view_string.pyx b/docs/examples/userguide/memoryviews/view_string.pyx index 7aace3ea5..9fdeae053 100644 --- a/docs/examples/userguide/memoryviews/view_string.pyx +++ b/docs/examples/userguide/memoryviews/view_string.pyx @@ -1,9 +1,9 @@ -cdef bint is_y_in(const unsigned char[:] string_view):
- cdef int i
- for i in range(string_view.shape[0]):
- if string_view[i] == b'y':
- return True
- return False
-
-print(is_y_in(b'hello world')) # False
-print(is_y_in(b'hello Cython')) # True
+cdef bint is_y_in(const unsigned char[:] string_view): + cdef int i + for i in range(string_view.shape[0]): + if string_view[i] == b'y': + return True + return False + +print(is_y_in(b'hello world')) # False +print(is_y_in(b'hello Cython')) # True diff --git a/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx b/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx index 2fc87907d..af5ef9071 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_fused_types.pyx @@ -1,44 +1,44 @@ -# cython: infer_types=True
-import numpy as np
-cimport cython
-
-ctypedef fused my_type:
- int
- double
- long long
-
-
-cdef my_type clip(my_type a, my_type min_value, my_type max_value):
- return min(max(a, min_value), max_value)
-
-
-@cython.boundscheck(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):
-
- x_max = array_1.shape[0]
- y_max = array_1.shape[1]
-
- assert tuple(array_1.shape) == tuple(array_2.shape)
-
- if my_type is int:
- dtype = np.intc
- elif my_type is double:
- dtype = np.double
- elif my_type is cython.longlong:
- dtype = np.longlong
-
- result = np.zeros((x_max, y_max), dtype=dtype)
- cdef my_type[:, ::1] result_view = result
-
- cdef my_type tmp
- cdef Py_ssize_t x, y
-
- for x in range(x_max):
- for y in range(y_max):
-
- tmp = clip(array_1[x, y], 2, 10)
- tmp = tmp * a + array_2[x, y] * b
- result_view[x, y] = tmp + c
-
- return result
+# cython: infer_types=True +import numpy as np +cimport cython + +ctypedef fused my_type: + int + double + long long + + +cdef my_type clip(my_type a, my_type min_value, my_type max_value): + return min(max(a, min_value), max_value) + + +@cython.boundscheck(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): + + x_max = array_1.shape[0] + y_max = array_1.shape[1] + + assert tuple(array_1.shape) == tuple(array_2.shape) + + if my_type is int: + dtype = np.intc + elif my_type is double: + dtype = np.double + elif my_type is cython.longlong: + dtype = np.longlong + + result = np.zeros((x_max, y_max), dtype=dtype) + cdef my_type[:, ::1] result_view = result + + cdef my_type tmp + cdef Py_ssize_t x, y + + for x in range(x_max): + for y in range(y_max): + + tmp = clip(array_1[x, y], 2, 10) + tmp = tmp * a + array_2[x, y] * b + result_view[x, y] = tmp + c + + return result diff --git a/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx b/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx index 98a683de7..3882c289d 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_infer_types.pyx @@ -1,34 +1,34 @@ -# cython: infer_types=True
-import numpy as np
-cimport cython
-
-DTYPE = np.intc
-
-
-cdef int clip(int a, int min_value, int max_value):
- return min(max(a, min_value), max_value)
-
-
-@cython.boundscheck(False)
-@cython.wraparound(False)
-def compute(int[:, ::1] array_1, int[:, ::1] array_2, int a, int b, int c):
-
- x_max = array_1.shape[0]
- y_max = array_1.shape[1]
-
- assert tuple(array_1.shape) == tuple(array_2.shape)
-
- result = np.zeros((x_max, y_max), dtype=DTYPE)
- cdef int[:, ::1] result_view = result
-
- cdef int tmp
- cdef Py_ssize_t x, y
-
- for x in range(x_max):
- for y in range(y_max):
-
- tmp = clip(array_1[x, y], 2, 10)
- tmp = tmp * a + array_2[x, y] * b
- result_view[x, y] = tmp + c
-
- return result
+# cython: infer_types=True +import numpy as np +cimport cython + +DTYPE = np.intc + + +cdef int clip(int a, int min_value, int max_value): + return min(max(a, min_value), max_value) + + +@cython.boundscheck(False) +@cython.wraparound(False) +def compute(int[:, ::1] array_1, int[:, ::1] array_2, int a, int b, int c): + + x_max = array_1.shape[0] + y_max = array_1.shape[1] + + assert tuple(array_1.shape) == tuple(array_2.shape) + + result = np.zeros((x_max, y_max), dtype=DTYPE) + cdef int[:, ::1] result_view = result + + cdef int tmp + cdef Py_ssize_t x, y + + for x in range(x_max): + for y in range(y_max): + + tmp = clip(array_1[x, y], 2, 10) + tmp = tmp * a + array_2[x, y] * b + result_view[x, y] = tmp + c + + return result diff --git a/docs/examples/userguide/numpy_tutorial/compute_memview.pyx b/docs/examples/userguide/numpy_tutorial/compute_memview.pyx index d264e773a..166cd6df3 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_memview.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_memview.pyx @@ -1,34 +1,34 @@ -import numpy as np
-
-DTYPE = np.intc
-
-
-cdef int clip(int a, int min_value, int max_value):
- return min(max(a, min_value), max_value)
-
-
-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 y_max = array_1.shape[1]
-
- # array_1.shape is now a C array, no it's not possible
- # to compare it simply by using == without a for-loop.
- # To be able to compare it to array_2.shape easily,
- # we convert them both to Python tuples.
- assert tuple(array_1.shape) == tuple(array_2.shape)
-
- result = np.zeros((x_max, y_max), dtype=DTYPE)
- cdef int[:, :] result_view = result
-
- cdef int tmp
- cdef Py_ssize_t x, y
-
- for x in range(x_max):
- for y in range(y_max):
-
- tmp = clip(array_1[x, y], 2, 10)
- tmp = tmp * a + array_2[x, y] * b
- result_view[x, y] = tmp + c
-
- return result
+import numpy as np + +DTYPE = np.intc + + +cdef int clip(int a, int min_value, int max_value): + return min(max(a, min_value), max_value) + + +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 y_max = array_1.shape[1] + + # array_1.shape is now a C array, no it's not possible + # to compare it simply by using == without a for-loop. + # To be able to compare it to array_2.shape easily, + # we convert them both to Python tuples. + assert tuple(array_1.shape) == tuple(array_2.shape) + + result = np.zeros((x_max, y_max), dtype=DTYPE) + cdef int[:, :] result_view = result + + cdef int tmp + cdef Py_ssize_t x, y + + for x in range(x_max): + for y in range(y_max): + + tmp = clip(array_1[x, y], 2, 10) + tmp = tmp * a + array_2[x, y] * b + result_view[x, y] = tmp + c + + return result diff --git a/docs/examples/userguide/numpy_tutorial/compute_prange.pyx b/docs/examples/userguide/numpy_tutorial/compute_prange.pyx index c00d2261b..562c73070 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_prange.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_prange.pyx @@ -1,53 +1,53 @@ -# tag: openmp
-# You can ignore the previous line.
-# It's for internal testing of the cython documentation.
-
-# distutils: extra_compile_args=-fopenmp
-# distutils: extra_link_args=-fopenmp
-
-import numpy as np
-cimport cython
-from cython.parallel import prange
-
-ctypedef fused my_type:
- int
- double
- long long
-
-
-# We declare our plain c function 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)
-
-
-@cython.boundscheck(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):
-
- cdef Py_ssize_t x_max = array_1.shape[0]
- cdef Py_ssize_t y_max = array_1.shape[1]
-
- assert tuple(array_1.shape) == tuple(array_2.shape)
-
- if my_type is int:
- dtype = np.intc
- elif my_type is double:
- dtype = np.double
- elif my_type is cython.longlong:
- dtype = np.longlong
-
- result = np.zeros((x_max, y_max), dtype=dtype)
- cdef my_type[:, ::1] result_view = result
-
- cdef my_type tmp
- cdef Py_ssize_t x, y
-
- # We use prange here.
- for x in prange(x_max, nogil=True):
- for y in range(y_max):
-
- tmp = clip(array_1[x, y], 2, 10)
- tmp = tmp * a + array_2[x, y] * b
- result_view[x, y] = tmp + c
-
- return result
+# tag: openmp +# You can ignore the previous line. +# It's for internal testing of the cython documentation. + +# distutils: extra_compile_args=-fopenmp +# distutils: extra_link_args=-fopenmp + +import numpy as np +cimport cython +from cython.parallel import prange + +ctypedef fused my_type: + int + double + long long + + +# We declare our plain c function 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) + + +@cython.boundscheck(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): + + cdef Py_ssize_t x_max = array_1.shape[0] + cdef Py_ssize_t y_max = array_1.shape[1] + + assert tuple(array_1.shape) == tuple(array_2.shape) + + if my_type is int: + dtype = np.intc + elif my_type is double: + dtype = np.double + elif my_type is cython.longlong: + dtype = np.longlong + + result = np.zeros((x_max, y_max), dtype=dtype) + cdef my_type[:, ::1] result_view = result + + cdef my_type tmp + cdef Py_ssize_t x, y + + # We use prange here. + for x in prange(x_max, nogil=True): + for y in range(y_max): + + tmp = clip(array_1[x, y], 2, 10) + tmp = tmp * a + array_2[x, y] * b + result_view[x, y] = tmp + c + + return result diff --git a/docs/examples/userguide/numpy_tutorial/compute_py.py b/docs/examples/userguide/numpy_tutorial/compute_py.py index 00bcf244c..4a5f90b4d 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_py.py +++ b/docs/examples/userguide/numpy_tutorial/compute_py.py @@ -1,28 +1,28 @@ -import numpy as np
-
-
-def clip(a, min_value, max_value):
- return min(max(a, min_value), max_value)
-
-
-def compute(array_1, array_2, a, b, c):
- """
- This function must implement the formula
- np.clip(array_1, 2, 10) * a + array_2 * b + c
-
- array_1 and array_2 are 2D.
- """
- x_max = array_1.shape[0]
- y_max = array_1.shape[1]
-
- assert array_1.shape == array_2.shape
-
- result = np.zeros((x_max, y_max), dtype=array_1.dtype)
-
- for x in range(x_max):
- for y in range(y_max):
- tmp = clip(array_1[x, y], 2, 10)
- tmp = tmp * a + array_2[x, y] * b
- result[x, y] = tmp + c
-
- return result
+import numpy as np + + +def clip(a, min_value, max_value): + return min(max(a, min_value), max_value) + + +def compute(array_1, array_2, a, b, c): + """ + This function must implement the formula + np.clip(array_1, 2, 10) * a + array_2 * b + c + + array_1 and array_2 are 2D. + """ + x_max = array_1.shape[0] + y_max = array_1.shape[1] + + assert array_1.shape == array_2.shape + + result = np.zeros((x_max, y_max), dtype=array_1.dtype) + + for x in range(x_max): + for y in range(y_max): + tmp = clip(array_1[x, y], 2, 10) + tmp = tmp * a + array_2[x, y] * b + result[x, y] = tmp + c + + return result diff --git a/docs/examples/userguide/numpy_tutorial/compute_typed.pyx b/docs/examples/userguide/numpy_tutorial/compute_typed.pyx index 8218aa709..cccc1aa3b 100644 --- a/docs/examples/userguide/numpy_tutorial/compute_typed.pyx +++ b/docs/examples/userguide/numpy_tutorial/compute_typed.pyx @@ -1,50 +1,50 @@ -import numpy as np
-
-# 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
-# type info object.
-DTYPE = np.intc
-
-# 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.
-cdef int clip(int a, int min_value, int max_value):
- return min(max(a, min_value), max_value)
-
-
-def compute(array_1, array_2, int a, int b, int c):
-
- # 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
- # problems with allowing them in other places, though we'd love to see
- # good and thought out proposals for it).
- cdef Py_ssize_t x_max = array_1.shape[0]
- cdef Py_ssize_t y_max = array_1.shape[1]
-
- assert array_1.shape == array_2.shape
- assert array_1.dtype == DTYPE
- assert array_2.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
- # warnings if not, only much slower code (they are implicitly typed as
- # Python objects).
- # 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.
- # 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
- # an error like in Python.
-
- cdef int tmp
-
- # Py_ssize_t is the proper C type for Python array indices.
- cdef Py_ssize_t x, y
-
- for x in range(x_max):
- for y in range(y_max):
-
- tmp = clip(array_1[x, y], 2, 10)
- tmp = tmp * a + array_2[x, y] * b
- result[x, y] = tmp + c
-
- return result
+import numpy as np + +# 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 +# type info object. +DTYPE = np.intc + +# 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. +cdef int clip(int a, int min_value, int max_value): + return min(max(a, min_value), max_value) + + +def compute(array_1, array_2, int a, int b, int c): + + # 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 + # problems with allowing them in other places, though we'd love to see + # good and thought out proposals for it). + cdef Py_ssize_t x_max = array_1.shape[0] + cdef Py_ssize_t y_max = array_1.shape[1] + + assert array_1.shape == array_2.shape + assert array_1.dtype == DTYPE + assert array_2.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 + # warnings if not, only much slower code (they are implicitly typed as + # Python objects). + # 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. + # 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 + # an error like in Python. + + cdef int tmp + + # Py_ssize_t is the proper C type for Python array indices. + cdef Py_ssize_t x, y + + for x in range(x_max): + for y in range(y_max): + + tmp = clip(array_1[x, y], 2, 10) + tmp = tmp * a + array_2[x, y] * b + result[x, y] = tmp + c + + return result diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc.py b/docs/examples/userguide/numpy_ufuncs/ufunc.py new file mode 100644 index 000000000..874183c84 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc.py @@ -0,0 +1,8 @@ +# tag: numpy +import cython + +@cython.ufunc +@cython.cfunc +def add_one(x: cython.double) -> cython.double: + # of course, this simple operation can already by done efficiently in Numpy! + return x+1 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc.pyx b/docs/examples/userguide/numpy_ufuncs/ufunc.pyx new file mode 100644 index 000000000..b29c071e1 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc.pyx @@ -0,0 +1,8 @@ +# tag: numpy +cimport cython + + +@cython.ufunc +cdef double add_one(double x): + # of course, this simple operation can already by done efficiently in Numpy! + return x+1 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.py b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.py new file mode 100644 index 000000000..b3f4fb6de --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.py @@ -0,0 +1,7 @@ +# tag: numpy +import cython + +@cython.ufunc +@cython.cfunc +def add_one_add_two(x: cython.int) -> tuple[cython.int, cython.int]: + return x+1, x+2 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx new file mode 100644 index 000000000..61127261c --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_ctuple.pyx @@ -0,0 +1,7 @@ +# tag: numpy +cimport cython + + +@cython.ufunc +cdef (int, int) add_one_add_two(int x): + return x+1, x+2 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_fused.py b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.py new file mode 100644 index 000000000..01cc3bc57 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.py @@ -0,0 +1,7 @@ +# tag: numpy +import cython + +@cython.ufunc +@cython.cfunc +def generic_add_one(x: cython.numeric) -> cython.numeric: + return x+1 diff --git a/docs/examples/userguide/numpy_ufuncs/ufunc_fused.pyx b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.pyx new file mode 100644 index 000000000..3baf58136 --- /dev/null +++ b/docs/examples/userguide/numpy_ufuncs/ufunc_fused.pyx @@ -0,0 +1,7 @@ +# tag: numpy +cimport cython + + +@cython.ufunc +cdef cython.numeric generic_add_one(cython.numeric x): + return x+1 diff --git a/docs/examples/userguide/parallelism/breaking_loop.py b/docs/examples/userguide/parallelism/breaking_loop.py new file mode 100644 index 000000000..00d0225b5 --- /dev/null +++ b/docs/examples/userguide/parallelism/breaking_loop.py @@ -0,0 +1,15 @@ +from cython.parallel import prange + +@cython.exceptval(-1) +@cython.cfunc +def func(n: cython.Py_ssize_t) -> cython.int: + i: cython.Py_ssize_t + + for i in prange(n, nogil=True): + if i == 8: + with cython.gil: + raise Exception() + elif i == 4: + break + elif i == 2: + return i diff --git a/docs/examples/userguide/parallelism/breaking_loop.pyx b/docs/examples/userguide/parallelism/breaking_loop.pyx index d11b179d9..e7445082d 100644 --- a/docs/examples/userguide/parallelism/breaking_loop.pyx +++ b/docs/examples/userguide/parallelism/breaking_loop.pyx @@ -1,13 +1,15 @@ -from cython.parallel import prange
-
-cdef int func(Py_ssize_t n):
- cdef Py_ssize_t i
-
- for i in prange(n, nogil=True):
- if i == 8:
- with gil:
- raise Exception()
- elif i == 4:
- break
- elif i == 2:
- return i
+from cython.parallel import prange + + + +cdef int func(Py_ssize_t n) except -1: + cdef Py_ssize_t i + + for i in prange(n, nogil=True): + if i == 8: + with gil: + raise Exception() + elif i == 4: + break + elif i == 2: + return i diff --git a/docs/examples/userguide/parallelism/cimport_openmp.py b/docs/examples/userguide/parallelism/cimport_openmp.py new file mode 100644 index 000000000..9288a4381 --- /dev/null +++ b/docs/examples/userguide/parallelism/cimport_openmp.py @@ -0,0 +1,11 @@ +# tag: openmp + +from cython.parallel import parallel +from cython.cimports.openmp import omp_set_dynamic, omp_get_num_threads + +num_threads = cython.declare(cython.int) + +omp_set_dynamic(1) +with cython.nogil, parallel(): + num_threads = omp_get_num_threads() + # ... diff --git a/docs/examples/userguide/parallelism/cimport_openmp.pyx b/docs/examples/userguide/parallelism/cimport_openmp.pyx index 235ee10bc..54d5f18db 100644 --- a/docs/examples/userguide/parallelism/cimport_openmp.pyx +++ b/docs/examples/userguide/parallelism/cimport_openmp.pyx @@ -1,13 +1,11 @@ -# tag: openmp
-# You can ignore the previous line.
-# It's for internal testing of the Cython documentation.
-
-from cython.parallel cimport parallel
-cimport openmp
-
-cdef int num_threads
-
-openmp.omp_set_dynamic(1)
-with nogil, parallel():
- num_threads = openmp.omp_get_num_threads()
- # ...
+# tag: openmp + +from cython.parallel cimport parallel +cimport openmp + +cdef int num_threads + +openmp.omp_set_dynamic(1) +with nogil, parallel(): + num_threads = openmp.omp_get_num_threads() + # ... diff --git a/docs/examples/userguide/parallelism/memoryview_sum.py b/docs/examples/userguide/parallelism/memoryview_sum.py new file mode 100644 index 000000000..6cff5d587 --- /dev/null +++ b/docs/examples/userguide/parallelism/memoryview_sum.py @@ -0,0 +1,7 @@ +from cython.parallel import prange + +def func(x: cython.double[:], alpha: cython.double): + i: cython.Py_ssize_t + + for i in prange(x.shape[0], nogil=True): + x[i] = alpha * x[i] diff --git a/docs/examples/userguide/parallelism/memoryview_sum.pyx b/docs/examples/userguide/parallelism/memoryview_sum.pyx new file mode 100644 index 000000000..bdc1c9feb --- /dev/null +++ b/docs/examples/userguide/parallelism/memoryview_sum.pyx @@ -0,0 +1,7 @@ +from cython.parallel import prange + +def func(double[:] x, double alpha): + cdef Py_ssize_t i + + for i in prange(x.shape[0], nogil=True): + x[i] = alpha * x[i] diff --git a/docs/examples/userguide/parallelism/parallel.py b/docs/examples/userguide/parallelism/parallel.py new file mode 100644 index 000000000..0fb62d10f --- /dev/null +++ b/docs/examples/userguide/parallelism/parallel.py @@ -0,0 +1,30 @@ +from cython.parallel import parallel, prange +from cython.cimports.libc.stdlib import abort, malloc, free + +@cython.nogil +@cython.cfunc +def func(buf: cython.p_int) -> cython.void: + pass + # ... + +idx = cython.declare(cython.Py_ssize_t) +i = cython.declare(cython.Py_ssize_t) +j = cython.declare(cython.Py_ssize_t) +n = cython.declare(cython.Py_ssize_t, 100) +local_buf = cython.declare(p_int) +size = cython.declare(cython.size_t, 10) + +with cython.nogil, parallel(): + local_buf: cython.p_int = cython.cast(cython.p_int, malloc(cython.sizeof(cython.int) * size)) + if local_buf is cython.NULL: + abort() + + # populate our local buffer in a sequential loop + for i in range(size): + local_buf[i] = i * 2 + + # share the work using the thread-local buffer(s) + for j in prange(n, schedule='guided'): + func(local_buf) + + free(local_buf) diff --git a/docs/examples/userguide/parallelism/parallel.pyx b/docs/examples/userguide/parallelism/parallel.pyx new file mode 100644 index 000000000..2a952d537 --- /dev/null +++ b/docs/examples/userguide/parallelism/parallel.pyx @@ -0,0 +1,30 @@ +from cython.parallel import parallel, prange +from libc.stdlib cimport abort, malloc, free + + + +cdef void func(int *buf) nogil: + pass + # ... + +cdef Py_ssize_t idx, i, j, n = 100 +cdef int * local_buf +cdef size_t size = 10 + + + + +with nogil, parallel(): + local_buf = <int *> malloc(sizeof(int) * size) + if local_buf is NULL: + abort() + + # populate our local buffer in a sequential loop + for i in range(size): + local_buf[i] = i * 2 + + # share the work using the thread-local buffer(s) + for j in prange(n, schedule='guided'): + func(local_buf) + + free(local_buf) diff --git a/docs/examples/userguide/parallelism/setup_py.py b/docs/examples/userguide/parallelism/setup_py.py new file mode 100644 index 000000000..85a037dc5 --- /dev/null +++ b/docs/examples/userguide/parallelism/setup_py.py @@ -0,0 +1,16 @@ +from setuptools import Extension, setup +from Cython.Build import cythonize + +ext_modules = [ + Extension( + "hello", + ["hello.py"], + extra_compile_args=['-fopenmp'], + extra_link_args=['-fopenmp'], + ) +] + +setup( + name='hello-parallel-world', + ext_modules=cythonize(ext_modules), +) diff --git a/docs/examples/userguide/parallelism/setup.py b/docs/examples/userguide/parallelism/setup_pyx.py index 0fb6026f7..fe6d0a64c 100644 --- a/docs/examples/userguide/parallelism/setup.py +++ b/docs/examples/userguide/parallelism/setup_pyx.py @@ -1,17 +1,16 @@ -from distutils.core import setup
-from distutils.extension import Extension
-from Cython.Build import cythonize
-
-ext_modules = [
- Extension(
- "hello",
- ["hello.pyx"],
- extra_compile_args=['-fopenmp'],
- extra_link_args=['-fopenmp'],
- )
-]
-
-setup(
- name='hello-parallel-world',
- ext_modules=cythonize(ext_modules),
-)
+from setuptools import Extension, setup +from Cython.Build import cythonize + +ext_modules = [ + Extension( + "hello", + ["hello.pyx"], + extra_compile_args=['-fopenmp'], + extra_link_args=['-fopenmp'], + ) +] + +setup( + name='hello-parallel-world', + ext_modules=cythonize(ext_modules), +) diff --git a/docs/examples/userguide/parallelism/simple_sum.py b/docs/examples/userguide/parallelism/simple_sum.py new file mode 100644 index 000000000..f952a8556 --- /dev/null +++ b/docs/examples/userguide/parallelism/simple_sum.py @@ -0,0 +1,10 @@ +from cython.parallel import prange + +i = cython.declare(cython.int) +n = cython.declare(cython.int, 30) +sum = cython.declare(cython.int, 0) + +for i in prange(n, nogil=True): + sum += i + +print(sum) diff --git a/docs/examples/userguide/parallelism/simple_sum.pyx b/docs/examples/userguide/parallelism/simple_sum.pyx index 83b862ea6..929a988e5 100644 --- a/docs/examples/userguide/parallelism/simple_sum.pyx +++ b/docs/examples/userguide/parallelism/simple_sum.pyx @@ -1,10 +1,10 @@ -from cython.parallel import prange
-
-cdef int i
-cdef int n = 30
-cdef int sum = 0
-
-for i in prange(n, nogil=True):
- sum += i
-
-print(sum)
+from cython.parallel import prange + +cdef int i +cdef int n = 30 +cdef int sum = 0 + +for i in prange(n, nogil=True): + sum += i + +print(sum) diff --git a/docs/examples/userguide/sharing_declarations/landscaping.py b/docs/examples/userguide/sharing_declarations/landscaping.py new file mode 100644 index 000000000..2d2c4b5b7 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/landscaping.py @@ -0,0 +1,7 @@ +from cython.cimports.shrubbing import Shrubbery +import shrubbing + +def main(): + sh: Shrubbery + sh = shrubbing.standard_shrubbery() + print("Shrubbery size is", sh.width, 'x', sh.length) diff --git a/docs/examples/userguide/sharing_declarations/landscaping.pyx b/docs/examples/userguide/sharing_declarations/landscaping.pyx index c54e74fd0..afc999e53 100644 --- a/docs/examples/userguide/sharing_declarations/landscaping.pyx +++ b/docs/examples/userguide/sharing_declarations/landscaping.pyx @@ -1,7 +1,7 @@ -cimport shrubbing
-import shrubbing
-
-def main():
- cdef shrubbing.Shrubbery sh
- sh = shrubbing.standard_shrubbery()
- print("Shrubbery size is", sh.width, 'x', sh.length)
+cimport shrubbing +import shrubbing + +def main(): + cdef shrubbing.Shrubbery sh + sh = shrubbing.standard_shrubbery() + print("Shrubbery size is", sh.width, 'x', sh.length) diff --git a/docs/examples/userguide/sharing_declarations/lunch.py b/docs/examples/userguide/sharing_declarations/lunch.py new file mode 100644 index 000000000..df56913eb --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/lunch.py @@ -0,0 +1,5 @@ +import cython +from cython.cimports.c_lunch import eject_tomato as c_eject_tomato + +def eject_tomato(speed: cython.float): + c_eject_tomato(speed) diff --git a/docs/examples/userguide/sharing_declarations/lunch.pyx b/docs/examples/userguide/sharing_declarations/lunch.pyx index 7bb2d4756..fea5e4c87 100644 --- a/docs/examples/userguide/sharing_declarations/lunch.pyx +++ b/docs/examples/userguide/sharing_declarations/lunch.pyx @@ -1,4 +1,5 @@ -cimport c_lunch
-
-def eject_tomato(float speed):
- c_lunch.eject_tomato(speed)
+ +cimport c_lunch + +def eject_tomato(float speed): + c_lunch.eject_tomato(speed) diff --git a/docs/examples/userguide/sharing_declarations/restaurant.py b/docs/examples/userguide/sharing_declarations/restaurant.py new file mode 100644 index 000000000..b4bdb2eba --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/restaurant.py @@ -0,0 +1,12 @@ +import cython +from cython.cimports.dishes import spamdish, sausage + +@cython.cfunc +def prepare(d: cython.pointer(spamdish)) -> cython.void: + d.oz_of_spam = 42 + d.filler = sausage + +def serve(): + d: spamdish + prepare(cython.address(d)) + print(f'{d.oz_of_spam} oz spam, filler no. {d.filler}') diff --git a/docs/examples/userguide/sharing_declarations/restaurant.pyx b/docs/examples/userguide/sharing_declarations/restaurant.pyx index 0c1dbf5c0..f556646dc 100644 --- a/docs/examples/userguide/sharing_declarations/restaurant.pyx +++ b/docs/examples/userguide/sharing_declarations/restaurant.pyx @@ -1,12 +1,12 @@ -from __future__ import print_function
-cimport dishes
-from dishes cimport spamdish
-
-cdef void prepare(spamdish *d):
- d.oz_of_spam = 42
- d.filler = dishes.sausage
-
-def serve():
- cdef spamdish d
- prepare(&d)
- print(f'{d.oz_of_spam} oz spam, filler no. {d.filler}')
+ +cimport dishes +from dishes cimport spamdish + +cdef void prepare(spamdish *d): + d.oz_of_spam = 42 + d.filler = dishes.sausage + +def serve(): + cdef spamdish d + prepare(&d) + print(f'{d.oz_of_spam} oz spam, filler no. {d.filler}') diff --git a/docs/examples/userguide/sharing_declarations/setup_py.py b/docs/examples/userguide/sharing_declarations/setup_py.py new file mode 100644 index 000000000..45ded0ff4 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/setup_py.py @@ -0,0 +1,4 @@ +from setuptools import setup +from Cython.Build import cythonize + +setup(ext_modules=cythonize(["landscaping.py", "shrubbing.py"])) diff --git a/docs/examples/userguide/sharing_declarations/setup.py b/docs/examples/userguide/sharing_declarations/setup_pyx.py index 64804f97d..505b53e9d 100644 --- a/docs/examples/userguide/sharing_declarations/setup.py +++ b/docs/examples/userguide/sharing_declarations/setup_pyx.py @@ -1,4 +1,4 @@ -from distutils.core import setup
-from Cython.Build import cythonize
-
-setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"]))
+from setuptools import setup +from Cython.Build import cythonize + +setup(ext_modules=cythonize(["landscaping.pyx", "shrubbing.pyx"])) diff --git a/docs/examples/userguide/sharing_declarations/shrubbing.py b/docs/examples/userguide/sharing_declarations/shrubbing.py new file mode 100644 index 000000000..27e20d631 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/shrubbing.py @@ -0,0 +1,10 @@ +import cython + +@cython.cclass +class Shrubbery: + def __cinit__(self, w: cython.int, l: cython.int): + self.width = w + self.length = l + +def standard_shrubbery(): + return Shrubbery(3, 7) diff --git a/docs/examples/userguide/sharing_declarations/shrubbing.pyx b/docs/examples/userguide/sharing_declarations/shrubbing.pyx index a8b70dae2..91235e5ec 100644 --- a/docs/examples/userguide/sharing_declarations/shrubbing.pyx +++ b/docs/examples/userguide/sharing_declarations/shrubbing.pyx @@ -1,7 +1,10 @@ -cdef class Shrubbery:
- def __cinit__(self, int w, int l):
- self.width = w
- self.length = l
-
-def standard_shrubbery():
- return Shrubbery(3, 7)
+ + + +cdef class Shrubbery: + def __init__(self, int w, int l): + self.width = w + self.length = l + +def standard_shrubbery(): + return Shrubbery(3, 7) diff --git a/docs/examples/userguide/sharing_declarations/spammery.py b/docs/examples/userguide/sharing_declarations/spammery.py new file mode 100644 index 000000000..88554be4a --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/spammery.py @@ -0,0 +1,10 @@ +import cython +from cython.cimports.volume import cube + +def menu(description, size): + print(description, ":", cube(size), + "cubic metres of spam") + +menu("Entree", 1) +menu("Main course", 3) +menu("Dessert", 2) diff --git a/docs/examples/userguide/sharing_declarations/spammery.pyx b/docs/examples/userguide/sharing_declarations/spammery.pyx index f65cf63d7..da11e737e 100644 --- a/docs/examples/userguide/sharing_declarations/spammery.pyx +++ b/docs/examples/userguide/sharing_declarations/spammery.pyx @@ -1,11 +1,10 @@ -from __future__ import print_function
-
-from volume cimport cube
-
-def menu(description, size):
- print(description, ":", cube(size),
- "cubic metres of spam")
-
-menu("Entree", 1)
-menu("Main course", 3)
-menu("Dessert", 2)
+ +from volume cimport cube + +def menu(description, size): + print(description, ":", cube(size), + "cubic metres of spam") + +menu("Entree", 1) +menu("Main course", 3) +menu("Dessert", 2) diff --git a/docs/examples/userguide/sharing_declarations/volume.pxd b/docs/examples/userguide/sharing_declarations/volume.pxd index 598efd922..a30c68e52 100644 --- a/docs/examples/userguide/sharing_declarations/volume.pxd +++ b/docs/examples/userguide/sharing_declarations/volume.pxd @@ -1 +1 @@ -cdef float cube(float)
+cdef float cube(float x) diff --git a/docs/examples/userguide/sharing_declarations/volume.py b/docs/examples/userguide/sharing_declarations/volume.py new file mode 100644 index 000000000..1f6ff9c72 --- /dev/null +++ b/docs/examples/userguide/sharing_declarations/volume.py @@ -0,0 +1,2 @@ +def cube(x): + return x * x * x diff --git a/docs/examples/userguide/sharing_declarations/volume.pyx b/docs/examples/userguide/sharing_declarations/volume.pyx index 0fbab6fb7..0476b6068 100644 --- a/docs/examples/userguide/sharing_declarations/volume.pyx +++ b/docs/examples/userguide/sharing_declarations/volume.pyx @@ -1,2 +1,2 @@ -cdef float cube(float x):
- return x * x * x
+cdef float cube(float x): + return x * x * x diff --git a/docs/examples/userguide/special_methods/total_ordering.py b/docs/examples/userguide/special_methods/total_ordering.py new file mode 100644 index 000000000..7d164d6df --- /dev/null +++ b/docs/examples/userguide/special_methods/total_ordering.py @@ -0,0 +1,13 @@ +import cython +@cython.total_ordering +@cython.cclass +class ExtGe: + x: cython.int + + def __ge__(self, other): + if not isinstance(other, ExtGe): + return NotImplemented + return self.x >= cython.cast(ExtGe, other).x + + def __eq__(self, other): + return isinstance(other, ExtGe) and self.x == cython.cast(ExtGe, other).x diff --git a/docs/examples/userguide/special_methods/total_ordering.pyx b/docs/examples/userguide/special_methods/total_ordering.pyx new file mode 100644 index 000000000..06d2ccef7 --- /dev/null +++ b/docs/examples/userguide/special_methods/total_ordering.pyx @@ -0,0 +1,13 @@ +import cython + +@cython.total_ordering +cdef class ExtGe: + cdef int x + + def __ge__(self, other): + if not isinstance(other, ExtGe): + return NotImplemented + return self.x >= (<ExtGe>other).x + + def __eq__(self, other): + return isinstance(other, ExtGe) and self.x == (<ExtGe>other).x diff --git a/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd b/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd index 68f949122..a26e69b51 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd +++ b/docs/examples/userguide/wrapping_CPlusPlus/Rectangle.pxd @@ -1,7 +1,7 @@ cdef extern from "Rectangle.cpp":
pass
-# Decalre the class with cdef
+# Declare the class with cdef
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
Rectangle() except +
diff --git a/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx b/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx index 24192bf96..d074fa5ab 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/cython_usage.pyx @@ -1,12 +1,12 @@ -# distutils: language = c++
-
-from Rectangle cimport Rectangle
-
-def main():
- rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap
- try:
- rec_area = rec_ptr.getArea()
- finally:
- del rec_ptr # delete heap allocated object
-
- cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack
+# distutils: language = c++ + +from Rectangle cimport Rectangle + +def main(): + rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap + try: + rec_area = rec_ptr.getArea() + finally: + del rec_ptr # delete heap allocated object + + cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack diff --git a/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx b/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx index 13c75426e..35d064fdd 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/function_templates.pyx @@ -1,7 +1,7 @@ -# distutils: language = c++
-
-cdef extern from "<algorithm>" namespace "std":
- T max[T](T a, T b)
-
-print(max[long](3, 4))
-print(max(1.5, 2.5)) # simple template argument deduction
+# distutils: language = c++ + +cdef extern from "<algorithm>" namespace "std": + T max[T](T a, T b) + +print(max[long](3, 4)) +print(max(1.5, 2.5)) # simple template argument deduction diff --git a/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx b/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx index ea0007e6a..cdce8910f 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/iterate.pyx @@ -1,12 +1,12 @@ -# distutils: language = c++
-
-from libcpp.vector cimport vector
-
-def main():
- cdef vector[int] v = [4, 6, 5, 10, 3]
-
- cdef int value
- for value in v:
- print(value)
-
- return [x*x for x in v if x % 2 == 0]
+# distutils: language = c++ + +from libcpp.vector cimport vector + +def main(): + cdef vector[int] v = [4, 6, 5, 10, 3] + + cdef int value + for value in v: + print(value) + + return [x*x for x in v if x % 2 == 0] diff --git a/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx b/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx index e53f39b98..c5c764468 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/nested_class.pyx @@ -1,17 +1,17 @@ -# distutils: language = c++
-
-cdef extern from "<vector>" namespace "std":
- cdef cppclass vector[T]:
- cppclass iterator:
- T operator*()
- iterator operator++()
- bint operator==(iterator)
- bint operator!=(iterator)
- vector()
- void push_back(T&)
- T& operator[](int)
- T& at(int)
- iterator begin()
- iterator end()
-
-cdef vector[int].iterator iter #iter is declared as being of type vector<int>::iterator
+# distutils: language = c++ + +cdef extern from "<vector>" namespace "std": + cdef cppclass vector[T]: + cppclass iterator: + T operator*() + iterator operator++() + bint operator==(iterator) + bint operator!=(iterator) + vector() + void push_back(T&) + T& operator[](int) + T& at(int) + iterator begin() + iterator end() + +cdef vector[int].iterator iter #iter is declared as being of type vector<int>::iterator diff --git a/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx b/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx index 30bdb7bcb..b4be72c16 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/python_to_cpp.pyx @@ -1,19 +1,19 @@ -# distutils: language = c++
-
-from libcpp.string cimport string
-from libcpp.vector cimport vector
-
-py_bytes_object = b'The knights who say ni'
-py_unicode_object = u'Those who hear them seldom live to tell the tale.'
-
-cdef string s = py_bytes_object
-print(s) # b'The knights who say ni'
-
-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.'
-
-cdef vector[int] vect = range(1, 10, 2)
-print(vect) # [1, 3, 5, 7, 9]
-
-cdef vector[string] cpp_strings = b'It is a good shrubbery'.split()
-print(cpp_strings[1]) # b'is'
+# distutils: language = c++ + +from libcpp.string cimport string +from libcpp.vector cimport vector + +py_bytes_object = b'The knights who say ni' +py_unicode_object = u'Those who hear them seldom live to tell the tale.' + +cdef string s = py_bytes_object +print(s) # b'The knights who say ni' + +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.' + +cdef vector[int] vect = range(1, 10, 2) +print(vect) # [1, 3, 5, 7, 9] + +cdef vector[string] cpp_strings = b'It is a good shrubbery'.split() +print(cpp_strings[1]) # b'is' diff --git a/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx b/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx index e7c4423ef..d8eec16ef 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/rect.pyx @@ -8,7 +8,7 @@ from Rectangle cimport Rectangle cdef class PyRectangle: cdef Rectangle c_rect # Hold a C++ instance which we're wrapping - def __cinit__(self, int x0, int y0, int x1, int y1): + def __init__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): diff --git a/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx b/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx index 508e55dc6..ec4b34ab4 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/rect_ptr.pyx @@ -1,12 +1,18 @@ -# distutils: language = c++
-
-from Rectangle cimport Rectangle
-
-cdef class PyRectangle:
- 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):
- self.c_rect = new Rectangle(x0, y0, x1, y1)
-
- def __dealloc__(self):
- del self.c_rect
+# distutils: language = c++ + +from Rectangle cimport Rectangle + +cdef class PyRectangle: + cdef Rectangle*c_rect # hold a pointer to the C++ instance which we're wrapping + + def __cinit__(self): + self.c_rect = new Rectangle() + + def __init__(self, int x0, int y0, int x1, int y1): + self.c_rect.x0 = x0 + self.c_rect.y0 = y0 + self.c_rect.x1 = x1 + self.c_rect.y1 = y1 + + def __dealloc__(self): + del self.c_rect diff --git a/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx b/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx index 1bac30dec..441292ace 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/rect_with_attributes.pyx @@ -5,7 +5,7 @@ from Rectangle cimport Rectangle cdef class PyRectangle: cdef Rectangle c_rect - def __cinit__(self, int x0, int y0, int x1, int y1): + def __init__(self, int x0, int y0, int x1, int y1): self.c_rect = Rectangle(x0, y0, x1, y1) def get_area(self): diff --git a/docs/examples/userguide/wrapping_CPlusPlus/setup.py b/docs/examples/userguide/wrapping_CPlusPlus/setup.py index 0c89865d6..09009d28d 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/setup.py +++ b/docs/examples/userguide/wrapping_CPlusPlus/setup.py @@ -1,4 +1,4 @@ -from distutils.core import setup +from setuptools import setup from Cython.Build import cythonize diff --git a/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx b/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx index 8e7383ca2..4ff232b82 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/templates.pyx @@ -1,30 +1,30 @@ -# distutils: language = c++
-
-# import dereference and increment operators
-from cython.operator cimport dereference as deref, preincrement as inc
-
-cdef extern from "<vector>" namespace "std":
- cdef cppclass vector[T]:
- cppclass iterator:
- T operator*()
- iterator operator++()
- bint operator==(iterator)
- bint operator!=(iterator)
- vector()
- void push_back(T&)
- T& operator[](int)
- T& at(int)
- iterator begin()
- iterator end()
-
-cdef vector[int] *v = new vector[int]()
-cdef int i
-for i in range(10):
- v.push_back(i)
-
-cdef vector[int].iterator it = v.begin()
-while it != v.end():
- print(deref(it))
- inc(it)
-
-del v
+# distutils: language = c++ + +# import dereference and increment operators +from cython.operator cimport dereference as deref, preincrement as inc + +cdef extern from "<vector>" namespace "std": + cdef cppclass vector[T]: + cppclass iterator: + T operator*() + iterator operator++() + bint operator==(iterator) + bint operator!=(iterator) + vector() + void push_back(T&) + T& operator[](int) + T& at(int) + iterator begin() + iterator end() + +cdef vector[int] *v = new vector[int]() +cdef int i +for i in range(10): + v.push_back(i) + +cdef vector[int].iterator it = v.begin() +while it != v.end(): + print(deref(it)) + inc(it) + +del v diff --git a/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx b/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx index d7fdfc969..f1697e1ec 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/vector_demo.pyx @@ -1,15 +1,15 @@ -# distutils: language = c++
-
-from libcpp.vector cimport vector
-
-cdef vector[int] vect
-cdef int i, x
-
-for i in range(10):
- vect.push_back(i)
-
-for i in range(10):
- print(vect[i])
-
-for x in vect:
- print(x)
+# distutils: language = c++ + +from libcpp.vector cimport vector + +cdef vector[int] vect +cdef int i, x + +for i in range(10): + vect.push_back(i) + +for i in range(10): + print(vect[i]) + +for x in vect: + print(x) diff --git a/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx b/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx index 592e83ad9..4cdf12fc2 100644 --- a/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx +++ b/docs/examples/userguide/wrapping_CPlusPlus/wrapper_vector.pyx @@ -1,17 +1,17 @@ -# distutils: language = c++
-
-from libcpp.vector cimport vector
-
-
-cdef class VectorStack:
- cdef vector[int] v
-
- def push(self, x):
- self.v.push_back(x)
-
- def pop(self):
- if self.v.empty():
- raise IndexError()
- x = self.v.back()
- self.v.pop_back()
- return x
+# distutils: language = c++ + +from libcpp.vector cimport vector + + +cdef class VectorStack: + cdef vector[int] v + + def push(self, x): + self.v.push_back(x) + + def pop(self): + if self.v.empty(): + raise IndexError() + x = self.v.back() + self.v.pop_back() + return x |