[Python-checkins] CVS: python/dist/src/Doc/api api.tex,1.56.2.8,1.56.2.9

Fred L. Drake fdrake@weyr.cnri.reston.va.us
Wed, 16 Feb 2000 11:07:46 -0500 (EST)


Update of /projects/cvsroot/python/dist/src/Doc/api
In directory weyr:/home/fdrake/projects/python/Doc-152p1/api

Modified Files:
      Tag: release152p1-patches
	api.tex 
Log Message:

Buffer interface documentation from Greg Stein <gstein@lyra.org>;
thanks!


Index: api.tex
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Doc/api/api.tex,v
retrieving revision 1.56.2.8
retrieving revision 1.56.2.9
diff -C2 -r1.56.2.8 -r1.56.2.9
*** api.tex	2000/02/03 18:23:34	1.56.2.8
--- api.tex	2000/02/16 16:07:43	1.56.2.9
***************
*** 1852,1858 ****
  
  \subsection{Buffer Objects \label{bufferObjects}}
  
! XXX need a real description of buffers and buffer ''segments.``
  
  \begin{cvardesc}{PyTypeObject}{PyBuffer_Type}
  The instance of \ctype{PyTypeObject} which represents the Python
--- 1852,1897 ----
  
  \subsection{Buffer Objects \label{bufferObjects}}
+ \sectionauthor{Greg Stein}{gstein@lyra.org}
  
! Python type objects can export a group of functions called the
! ``buffer interface.'' These functions can be used by an object to
! expose its data in a raw, byte-oriented format. Clients of the object
! can use the buffer interface to access the object data directly,
! without needing to copy it first.
! 
! Two examples of objects that support 
! the buffer interface are strings and arrays. The string object exposes 
! the character contents in the buffer interface's byte-oriented
! form. An array can also expose its contents, but it should be noted
! that array elements may be multi-byte values.
! 
! An example user of the buffer interface is the file object's
! \method{write()} method. Any object that can export a series of bytes
! through the buffer interface can be written to a file. There are a
! number of format codes to \cfunction{PyArgs_ParseTuple()} that operate 
! against an object's buffer interface, returning data from the target
! object.
! 
! More information on the buffer interface is provided in the section
! \ref{newTypes}, under the description for \ctype{PyBufferProcs}.
  
+ A ``buffer object'' is defined in the \file{bufferobject.h} header
+ (included by \file{Python.h}). These objects look very similar to
+ string objects at the Python programming level: they support slicing,
+ indexing, concatenation, and some other standard string
+ operations. However, their data can come from one of two sources: from
+ a block of memory, or from another object which exports the buffer
+ interface.
+ 
+ Buffer objects are useful as a way to expose the data from another
+ object's buffer interface to the Python programmer. They can also be
+ used as a zero-copy slicing mechanism. Using their ability to
+ reference a block of memory, it is possible to expose any data to the
+ Python programmer quite easily. The memory could be a large, constant
+ array in a C extension, it could be a raw block of memory for
+ manipulation before passing to an operating system library, or it
+ could be used to pass around structured data in its native, in-memory
+ format.
+ 
  \begin{cvardesc}{PyTypeObject}{PyBuffer_Type}
  The instance of \ctype{PyTypeObject} which represents the Python
***************
*** 1861,1865 ****
  
  \begin{cvardesc}{int}{Py_END_OF_BUFFER}
! Constant returned by \cfunction{Py}
  \end{cvardesc}
  
--- 1900,1910 ----
  
  \begin{cvardesc}{int}{Py_END_OF_BUFFER}
! This constant may be passed as the \var{size} parameter to
! \cfunction{PyBuffer_FromObject()} or
! \cfunction{PyBuffer_FromReadWriteObject()}. It indicates that the new
! \ctype{PyBufferObject} should refer to \var{base} object from the
! specified \var{offset} to the end of its exported buffer. Using this
! enables the caller to avoid querying the \var{base} object for its
! length.
  \end{cvardesc}
  
***************
*** 1870,1878 ****
  \begin{cfuncdesc}{PyObject*}{PyBuffer_FromObject}{PyObject *base,
                                                    int offset, int size}
! Return a new read-only buffer object.
! Raises \exception{TypeError} if \var{base} doesn't support the
! read-only buffer protocol or doesn't provide exactly one buffer
! segment.  Raises \exception{ValueError} if \var{offset} is less than
! zero.
  \end{cfuncdesc}
  
--- 1915,1928 ----
  \begin{cfuncdesc}{PyObject*}{PyBuffer_FromObject}{PyObject *base,
                                                    int offset, int size}
! Return a new read-only buffer object.  This raises
! \exception{TypeError} if \var{base} doesn't support the read-only
! buffer protocol or doesn't provide exactly one buffer segment, or it
! raises \exception{ValueError} if \var{offset} is less than zero. The
! buffer will hold a reference to the \var{base} object, and the
! buffer's contents will refer to the \var{base} object's buffer
! interface, starting as position \var{offset} and extending for
! \var{size} bytes. If \var{size} is \constant{Py_END_OF_BUFFER}, then
! the new buffer's contents extend to the length of the \var{base}
! object's exported buffer data.
  \end{cfuncdesc}
  
***************
*** 1882,1906 ****
  Return a new writable buffer object.  Parameters and exceptions are
  similar to those for \cfunction{PyBuffer_FromObject()}.
  \end{cfuncdesc}
  
  \begin{cfuncdesc}{PyObject*}{PyBuffer_FromMemory}{void *ptr, int size}
! Return a new read-only buffer object that reads from a memory buffer.
  The caller is responsible for ensuring that the memory buffer, passed
  in as \var{ptr}, is not deallocated while the returned buffer object
  exists.  Raises \exception{ValueError} if \var{size} is less than
  zero.
  \end{cfuncdesc}
  
  \begin{cfuncdesc}{PyObject*}{PyBuffer_FromReadWriteMemory}{void *ptr, int size}
! Return a new writable buffer object that reads from and writes to a
! memory buffer.  The caller is responsible for ensuring that the memory
! buffer, passed in as \var{ptr}, is not deallocated while the returned
! buffer object exists.  Raises \exception{ValueError} if \var{size} is
! less than zero.
  \end{cfuncdesc}
  
  \begin{cfuncdesc}{PyObject*}{PyBuffer_New}{int size}
  Returns a new writable buffer object that maintains its own memory
! buffer of \var{size} bytes.  \var{size} must be zero or positive.
  \end{cfuncdesc}
  
--- 1932,1961 ----
  Return a new writable buffer object.  Parameters and exceptions are
  similar to those for \cfunction{PyBuffer_FromObject()}.
+ 
+ If the \var{base} object does not export the writeable buffer
+ protocol, then \exception{TypeError} is raised.
  \end{cfuncdesc}
  
  \begin{cfuncdesc}{PyObject*}{PyBuffer_FromMemory}{void *ptr, int size}
! Return a new read-only buffer object that reads from a specified
! location in memory, with a specified size.
  The caller is responsible for ensuring that the memory buffer, passed
  in as \var{ptr}, is not deallocated while the returned buffer object
  exists.  Raises \exception{ValueError} if \var{size} is less than
  zero.
+ 
+ Note that \constant{Py_END_OF_BUFFER} may \emph{not} be passed for the
+ \var{size} parameter.
  \end{cfuncdesc}
  
  \begin{cfuncdesc}{PyObject*}{PyBuffer_FromReadWriteMemory}{void *ptr, int size}
! Similar to \cfunction{PyBuffer_FromMemory()}, but the returned buffer
! is writable.
  \end{cfuncdesc}
  
  \begin{cfuncdesc}{PyObject*}{PyBuffer_New}{int size}
  Returns a new writable buffer object that maintains its own memory
! buffer of \var{size} bytes.  \exception{ValueError} is returned if
! \var{size} is not zero or positive.
  \end{cfuncdesc}
  
***************
*** 2572,2577 ****
  extension is imported after the interpreter has been completely
  re-initialized by calling \cfunction{Py_Finalize()} and
! \cfunction{Py_Initialize()}; in that case, the extension's \code{init}
! function \emph{is} called again.
  
  \strong{Bugs and caveats:} Because sub-interpreters (and the main 
--- 2627,2632 ----
  extension is imported after the interpreter has been completely
  re-initialized by calling \cfunction{Py_Finalize()} and
! \cfunction{Py_Initialize()}; in that case, the extension's
! \code{init\var{module}} function \emph{is} called again.
  
  \strong{Bugs and caveats:} Because sub-interpreters (and the main 
***************
*** 3107,3114 ****
  unaryfunc, binaryfunc, ternaryfunc, inquiry, coercion, intargfunc,
  intintargfunc, intobjargproc, intintobjargproc, objobjargproc,
- getreadbufferproc, getsegcountproc, getcharbufferproc,
  destructor, printfunc, getattrfunc, getattrofunc, setattrfunc,
  setattrofunc, cmpfunc, reprfunc, hashfunc
  
  \begin{ctypedesc}{int (*getwritebufferproc) (PyObject *self, int segment,
                                               void **ptrptr)}
--- 3162,3172 ----
  unaryfunc, binaryfunc, ternaryfunc, inquiry, coercion, intargfunc,
  intintargfunc, intobjargproc, intintobjargproc, objobjargproc,
  destructor, printfunc, getattrfunc, getattrofunc, setattrfunc,
  setattrofunc, cmpfunc, reprfunc, hashfunc
  
+ \begin{ctypedesc}{int (*getreadbufferproc) (PyObject *self, int segment,
+                                             void **ptrptr)}
+ \end{ctypedesc}
+ 
  \begin{ctypedesc}{int (*getwritebufferproc) (PyObject *self, int segment,
                                               void **ptrptr)}
***************
*** 3120,3125 ****
--- 3178,3193 ----
  \var{segment} specifies a segment that doesn't exist.
  % Why doesn't it raise ValueError for this one?
+ % GJS: because you shouldn't be calling it with an invalid
+ %      segment. That indicates a blatant programming error in the C
+ %      code.
+ \end{ctypedesc}
+ 
+ \begin{ctypedesc}{int (*getsegcountproc) (PyObject *self, int *lenp)}
  \end{ctypedesc}
  
+ \begin{ctypedesc}{int (*getcharbufferproc) (PyObject *self, int segment,
+                                             const char **ptrptr)}
+ \end{ctypedesc}
+ 
  PyNumberMethods
  
***************
*** 3127,3132 ****
  
  PyMappingMethods
  
! PyBufferProcs
  
  PyTypeObject
--- 3195,3268 ----
  
  PyMappingMethods
+ 
+ \begin{ctypedesc}{PyBufferProcs}
+ \code{PyBufferProcs} defines a set of slots for a Python type
+ object. These slots are used to implement the ``buffer interface.''
+ 
+ The buffer interface exports a model where an object can expose its
+ internal data as a set of chunks of data, each chunk specified as a
+ pointer/length pair. These chunks are called
+ ``segments'' and are presumed to be non-contiguous in memory.
+ 
+ If an object does not export the buffer interface, then its
+ \member{tp_as_buffer} member in the \ctype{PyTypeObject} structure
+ should be \NULL{}. Otherwise, \member{tp_as_buffer} will point to a
+ \ctype{PyBufferProcs} structure.
+ 
+ \emph{Note:} it is very important that your \ctype{PyTypeObject}
+ structure uses \code{Py_TPFLAGS_DEFAULT} for the value of the
+ \member{tp_flags} member. This tells the Python runtime that your
+ \ctype{PyBufferProcs} structure contains the \member{bf_getcharbuffer} 
+ slot. Older versions of Python did not have this member, so a new
+ Python interpreter using an old extension needs to be able to test for 
+ its presence before using it.
+ 
+ The first slot in the \ctype{PyBufferProcs} structure is
+ \member{bf_getreadbuffer}, which has type
+ \ctype{getreadbufferproc}. If this slot is \NULL{}, then the object does
+ not support reading from the internal data. This is non-sensical, so
+ implementors should fill this in. The read-buffer function is allowed
+ to raise an exception and return \code{-1}. Callers should test for
+ \NULL{} before using the slot and should check for an exception. The
+ \var{segment} which is passed must be zero or positive, and strictly less
+ than the number of segments returned by the \member{bf_getsegcount}
+ slot function.
+ 
+ The next slot is \member{bf_getwritebuffer} having type
+ \ctype{getwritebufferproc}. This slot may be \NULL{} if the object
+ does not allow writing into its returned buffers. If the slot function 
+ is present, it is allowed to raise an exception and return \code{-1}.
+ The \var{segment} follows the same restrictions as for
+ \member{bf_getreadbuffer}.
+ 
+ The third slot is \member{bf_getsegcount}, with type
+ \ctype{getsegcountproc}. This slot must not be \NULL{} and is used to
+ inform the caller how many segments the object contains. Simple
+ objects such as \ctype{PyString_Type} and \ctype{PyBuffer_Type}
+ objects contain a single segment. The \var{lenp} parameter may be
+ \NULL{}. If not, then the implementation should store the total size of all 
+ buffer segments into \code{*lenp}.
+ 
+ The last slot is \member{bf_getcharbuffer}, which has type
+ \ctype{getcharbufferproc}. This slot will only be present if the
+ \code{Py_TPFLAGS_HAVE_GETCHARBUFFER} flag is present in
+ \member{tp_flags} of the object's \ctype{PyTypeObject}. Before using
+ this slot, the caller should test whether it is present by using the
+ \cfunction{PyType_HasFeature()} macro. Assuming the slot is present,
+ then it may be \NULL{} indicating that the object's contents cannot be 
+ used a \emph{8-bit characters}. The slot function may also raise an
+ error if the object's contents cannot be interpreted as 8-bit
+ characters. For example, if the object is an array 
+ which is configured to hold floating point values, an exception may be 
+ raised if a caller attempts to use \member{bf_getcharbuffer} to fetch
+ a sequence of 8-bit characters. This notion of exporting the internal
+ buffers as ``text'' is used to distinguish between objects that are
+ binary in nature, and those which have character-based content.
+ 
+ \emph{Note:} the current policy seems to state that these
+ characters may be multi-byte characters. This implies that a buffer
+ size of \var{N} does not mean there are \var{N} characters present.
  
! \end{ctypedesc}
  
  PyTypeObject