From abd887d690f5a162c0feaa4ccddf736517501f19 Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Tue, 6 Mar 2012 14:55:06 +0100 Subject: [PATCH] Issue #14181: Improve clarity in the documentation for the multi-purpose Py_buffer.obj field. --- Doc/c-api/buffer.rst | 20 ++++++++++++------ Doc/c-api/typeobj.rst | 48 ++++++++++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/Doc/c-api/buffer.rst b/Doc/c-api/buffer.rst index 2d199922f2e..d636935754e 100644 --- a/Doc/c-api/buffer.rst +++ b/Doc/c-api/buffer.rst @@ -81,17 +81,23 @@ allows them to be created and copied very simply. When a generic wrapper around a buffer is needed, a :ref:`memoryview ` object can be created. +For short instructions how to write an exporting object, see +:ref:`Buffer Object Structures `. For obtaining +a buffer, see :c:func:`PyObject_GetBuffer`. .. c:type:: Py_buffer .. c:member:: void \*obj - A new reference to the exporting object or *NULL*. The reference is owned - by the consumer and automatically decremented and set to *NULL* by - :c:func:`PyBuffer_Release`. + A new reference to the exporting object. The reference is owned by + the consumer and automatically decremented and set to *NULL* by + :c:func:`PyBuffer_Release`. The field is the equivalent of the return + value of any standard C-API function. - For temporary buffers that are wrapped by :c:func:`PyMemoryView_FromBuffer` - this field must be *NULL*. + As a special case, for *temporary* buffers that are wrapped by + :c:func:`PyMemoryView_FromBuffer` or :c:func:`PyBuffer_FillInfo` + this field is *NULL*. In general, exporting objects MUST NOT + use this scheme. .. c:member:: void \*buf @@ -423,7 +429,9 @@ Buffer-related functions return -1. On success, fill in *view*, set :c:member:`view->obj` to a new reference - to *exporter* and return 0. + to *exporter* and return 0. In the case of chained buffer providers + that redirect requests to a single object, :c:member:`view->obj` MAY + refer to this object instead of *exporter* (See :ref:`Buffer Object Structures `). Successful calls to :c:func:`PyObject_GetBuffer` must be paired with calls to :c:func:`PyBuffer_Release`, similar to :c:func:`malloc` and :c:func:`free`. diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index b15d927719f..ea1a0ad9718 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1213,18 +1213,29 @@ Buffer Object Structures int (PyObject *exporter, Py_buffer *view, int flags); Handle a request to *exporter* to fill in *view* as specified by *flags*. - A standard implementation of this function will take these steps: + Except for point (3), an implementation of this function MUST take these + steps: - - Check if the request can be met. If not, raise :c:data:`PyExc_BufferError`, - set :c:data:`view->obj` to *NULL* and return -1. + (1) Check if the request can be met. If not, raise :c:data:`PyExc_BufferError`, + set :c:data:`view->obj` to *NULL* and return -1. - - Fill in the requested fields. + (2) Fill in the requested fields. - - Increment an internal counter for the number of exports. + (3) Increment an internal counter for the number of exports. - - Set :c:data:`view->obj` to *exporter* and increment :c:data:`view->obj`. + (4) Set :c:data:`view->obj` to *exporter* and increment :c:data:`view->obj`. - - Return 0. + (5) Return 0. + + If *exporter* is part of a chain or tree of buffer providers, two main + schemes can be used: + + * Re-export: Each member of the tree acts as the exporting object and + sets :c:data:`view->obj` to a new reference to itself. + + * Redirect: The buffer request is redirected to the root object of the + tree. Here, :c:data:`view->obj` will be a new reference to the root + object. The individual fields of *view* are described in section :ref:`Buffer structure `, the rules how an exporter @@ -1233,8 +1244,9 @@ Buffer Object Structures All memory pointed to in the :c:type:`Py_buffer` structure belongs to the exporter and must remain valid until there are no consumers left. - :c:member:`~Py_buffer.shape`, :c:member:`~Py_buffer.strides`, - :c:member:`~Py_buffer.suboffsets` and :c:member:`~Py_buffer.internal` + :c:member:`~Py_buffer.format`, :c:member:`~Py_buffer.shape`, + :c:member:`~Py_buffer.strides`, :c:member:`~Py_buffer.suboffsets` + and :c:member:`~Py_buffer.internal` are read-only for the consumer. :c:func:`PyBuffer_FillInfo` provides an easy way of exposing a simple @@ -1250,21 +1262,23 @@ Buffer Object Structures void (PyObject *exporter, Py_buffer *view); Handle a request to release the resources of the buffer. If no resources - need to be released, this field may be *NULL*. A standard implementation - of this function will take these steps: + need to be released, :c:member:`PyBufferProcs.bf_releasebuffer` may be + *NULL*. Otherwise, a standard implementation of this function will take + these optional steps: - - Decrement an internal counter for the number of exports. + (1) Decrement an internal counter for the number of exports. - - If the counter is 0, free all memory associated with *view*. + (2) If the counter is 0, free all memory associated with *view*. The exporter MUST use the :c:member:`~Py_buffer.internal` field to keep - track of buffer-specific resources (if present). This field is guaranteed - to remain constant, while a consumer MAY pass a copy of the original buffer - as the *view* argument. + track of buffer-specific resources. This field is guaranteed to remain + constant, while a consumer MAY pass a copy of the original buffer as the + *view* argument. This function MUST NOT decrement :c:data:`view->obj`, since that is - done automatically in :c:func:`PyBuffer_Release`. + done automatically in :c:func:`PyBuffer_Release` (this scheme is + useful for breaking reference cycles). :c:func:`PyBuffer_Release` is the interface for the consumer that