summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMatus Valo <matusvalo@users.noreply.github.com>2022-10-08 09:30:49 +0200
committerGitHub <noreply@github.com>2022-10-08 08:30:49 +0100
commite1364b5a4b546be34829360d0d1471bc33c01262 (patch)
tree011ce01eac6ae8c7e6a97ddcfca0b08cc21d0e00 /docs
parent1e84f30a4a397cecb888997fc97f5c2604af0733 (diff)
downloadcython-e1364b5a4b546be34829360d0d1471bc33c01262.tar.gz
Docs: Migrate buffer userguide to pure python (#5069)
Diffstat (limited to 'docs')
-rw-r--r--docs/examples/userguide/buffer/matrix.py15
-rw-r--r--docs/examples/userguide/buffer/matrix.pyx3
-rw-r--r--docs/examples/userguide/buffer/matrix_with_buffer.py48
-rw-r--r--docs/examples/userguide/buffer/matrix_with_buffer.pyx5
-rw-r--r--docs/examples/userguide/buffer/view_count.py30
-rw-r--r--docs/examples/userguide/buffer/view_count.pyx3
-rw-r--r--docs/src/userguide/buffer.rst34
7 files changed, 131 insertions, 7 deletions
diff --git a/docs/examples/userguide/buffer/matrix.py b/docs/examples/userguide/buffer/matrix.py
new file mode 100644
index 000000000..79a3d3f12
--- /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.unsigned
+ v: vector[cython.float]
+
+ def __cinit__(self, ncols: cython.unsigned):
+ 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 ca597c2f2..f2547f6c3 100644
--- a/docs/examples/userguide/buffer/matrix.pyx
+++ b/docs/examples/userguide/buffer/matrix.pyx
@@ -1,9 +1,8 @@
# distutils: language = c++
-# matrix.pyx
-
from libcpp.vector cimport vector
+
cdef class Matrix:
cdef unsigned ncols
cdef vector[float] v
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 46af91b07..16239d199 100644
--- a/docs/examples/userguide/buffer/matrix_with_buffer.pyx
+++ b/docs/examples/userguide/buffer/matrix_with_buffer.pyx
@@ -1,8 +1,8 @@
# 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]
@@ -27,6 +27,9 @@ cdef class Matrix:
# 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])
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 8027f3ee9..8c4b1d524 100644
--- a/docs/examples/userguide/buffer/view_count.pyx
+++ b/docs/examples/userguide/buffer/view_count.pyx
@@ -3,6 +3,7 @@
from cpython cimport Py_buffer
from libcpp.vector cimport vector
+
cdef class Matrix:
cdef int view_count
@@ -26,4 +27,4 @@ cdef class Matrix:
self.view_count += 1
def __releasebuffer__(self, Py_buffer *buffer):
- self.view_count -= 1 \ No newline at end of file
+ self.view_count -= 1
diff --git a/docs/src/userguide/buffer.rst b/docs/src/userguide/buffer.rst
index 08661a184..3687cf2fd 100644
--- a/docs/src/userguide/buffer.rst
+++ b/docs/src/userguide/buffer.rst
@@ -3,6 +3,10 @@
Implementing the buffer protocol
================================
+.. include::
+ ../two-syntax-variants-used
+
+
Cython objects can expose memory buffers to Python code
by implementing the "buffer protocol".
This chapter shows how to implement the protocol
@@ -16,7 +20,15 @@ The following Cython/C++ code implements a matrix of floats,
where the number of columns is fixed at construction time
but rows can be added dynamically.
-.. literalinclude:: ../../examples/userguide/buffer/matrix.pyx
+.. tabs::
+
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/userguide/buffer/matrix.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/userguide/buffer/matrix.pyx
There are no methods to do anything productive with the matrices' contents.
We could implement custom ``__getitem__``, ``__setitem__``, etc. for this,
@@ -27,7 +39,15 @@ Implementing the buffer protocol requires adding two methods,
``__getbuffer__`` and ``__releasebuffer__``,
which Cython handles specially.
-.. literalinclude:: ../../examples/userguide/buffer/matrix_with_buffer.pyx
+.. tabs::
+
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/userguide/buffer/matrix_with_buffer.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/userguide/buffer/matrix_with_buffer.pyx
The method ``Matrix.__getbuffer__`` fills a descriptor structure,
called a ``Py_buffer``, that is defined by the Python C-API.
@@ -75,7 +95,15 @@ This is where ``__releasebuffer__`` comes in.
We can add a reference count to each matrix,
and lock it for mutation whenever a view exists.
-.. literalinclude:: ../../examples/userguide/buffer/view_count.pyx
+.. tabs::
+
+ .. group-tab:: Pure Python
+
+ .. literalinclude:: ../../examples/userguide/buffer/view_count.py
+
+ .. group-tab:: Cython
+
+ .. literalinclude:: ../../examples/userguide/buffer/view_count.pyx
Flags
-----