#
10.7 Buffer Object Structures

The buffer interface exports a model where an object can expose its internal data as a set of chunks of data, where each chunk is 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 `tp_as_buffer` member in the `PyTypeObject` structure should be `NULL`. Otherwise, the `tp_as_buffer` will point to a `PyBufferProcs` structure.

Note: It is very important that your `PyTypeObject` structure uses `Py_TPFLAGS_DEFAULT` for the value of the `tp_flags` member rather than `0`. This tells the Python runtime that your `PyBufferProcs` structure contains the `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.

`PyBufferProcs`
  Structure used to hold the function pointers which define an implementation of the buffer protocol.

  The first slot is `bf_getreadbuffer`, of type `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, but callers should test that the slot contains a non-`NULL` value.

  The next slot is `bf_getwritebuffer` having type `getwritebufferproc`. This slot may be `NULL` if the object does not allow writing into its returned buffers.

  The third slot is `bf_getsegcount`, with type `getsegcountproc`. This slot must not be `NULL` and is used to inform the caller how many segments the object contains. Simple objects such as `PyString_Type` and `PyBuffer_Type` objects contain a single segment.

  The last slot is `bf_getcharbuffer`, of type `getcharbufferproc`. This slot will only be present if the `Py_TPFLAGS_HAVE_GETCHARBUFFER` flag is present in the `tp_flags` field of the object's `PyTypeObject`. Before using this slot, the caller should test whether it is present by using the `PyType_HasFeature()` function. If the flag is present, `bf_getcharbuffer` may be `NULL`, indicating that the object's contents cannot be used as 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 `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.

  Note: The current policy seems to state that these characters may be multi-byte characters. This implies that a buffer size of N does not mean there are N characters present.

`Py_TPFLAGS_HAVE_GETCHARBUFFER`
  Flag bit set in the type structure to indicate that the `bf_getcharbuffer` slot is known. This being set does not indicate that the object supports the buffer interface or that the `bf_getcharbuffer` slot is non-`NULL`.

`Py_ssize_t (*readbufferproc) (PyObject *self, Py_ssize_t segment, void **ptrptr)`
  Return a pointer to a readable segment of the buffer in `*ptrptr`. This function is allowed to raise an exception, in which case it must return `-1`. The segment which is specified must be zero or positive, and strictly less than the number of segments returned by the `bf_getsegcount` slot function. On success, it returns the length of the segment, and sets `*ptrptr` to a pointer to that memory.

`Py_ssize_t (*writebufferproc) (PyObject *self, Py_ssize_t segment, void **ptrptr)`
  Return a pointer to a writable memory buffer in `*ptrptr`, and the length of that segment as the function return value. The memory buffer must correspond to buffer segment segment. Must return `-1` and set an exception on error. `TypeError` should be raised if the object only supports read-only buffers, and `SystemError` should be raised when segment specifies a segment that doesn't exist.

`Py_ssize_t (*segcountproc) (PyObject *self, Py_ssize_t *lenp)`
  Return the number of memory segments which comprise the buffer. If lenp is not `NULL`, the implementation must report the sum of the sizes (in bytes) of all segments in `*lenp`. The function cannot fail.

`Py_ssize_t (*charbufferproc) (PyObject *self, Py_ssize_t segment, const char **ptrptr)`
  Return the size of the segment segment that ptrptr is set to. `*ptrptr` is set to the memory buffer. Returns `-1` on error.