From 33451d8ab143fb89374673d3aa751910c5b1031e Mon Sep 17 00:00:00 2001 From: "Travis E. Oliphant" Date: Mon, 17 Mar 2008 17:36:12 +0000 Subject: [PATCH] Add necessary headers to back-port new buffer protocol to Python 2.6 --- Include/abstract.h | 103 +++++++++++++++++++++++++++++++++++++++++++++ Include/object.h | 68 ++++++++++++++++++++++++++++++ Include/pyerrors.h | 2 + 3 files changed, 173 insertions(+) diff --git a/Include/abstract.h b/Include/abstract.h index c61cc8be3a4..159e67d7f21 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -529,6 +529,109 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ */ + /* new buffer API */ + +#define PyObject_CheckBuffer(obj) \ + (((obj)->ob_type->tp_as_buffer != NULL) && \ + ((obj)->ob_type->tp_as_buffer->bf_getbuffer != NULL)) + + /* Return 1 if the getbuffer function is available, otherwise + return 0 */ + + PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view, + int flags); + + /* This is a C-API version of the getbuffer function call. It checks + to make sure object has the required function pointer and issues the + call. Returns -1 and raises an error on failure and returns 0 on + success + */ + + + PyAPI_FUNC(void) PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view); + + + /* C-API version of the releasebuffer function call. It + checks to make sure the object has the required function + pointer and issues the call. The obj must have the buffer + interface or this function will cause a segfault (i.e. it + is assumed to be called only after a corresponding + getbuffer which already verified the existence of the + tp_as_buffer pointer). + + Returns 0 on success and -1 (with an error raised) on + failure. This function always succeeds (as a NO-OP) if + there is no releasebuffer function for the object so that + it can always be called when the consumer is done with the + buffer + */ + + PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); + + /* Get the memory area pointed to by the indices for the buffer given. + Note that view->ndim is the assumed size of indices + */ + + PyAPI_FUNC(int) PyBuffer_SizeFromFormat(const char *); + + /* Return the implied itemsize of the data-format area from a + struct-style description */ + + + + PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view, + Py_ssize_t len, char fort); + + PyAPI_FUNC(int) PyBuffer_FromContiguous(Py_buffer *view, void *buf, + Py_ssize_t len, char fort); + + + /* Copy len bytes of data from the contiguous chunk of memory + pointed to by buf into the buffer exported by obj. Return + 0 on success and return -1 and raise a PyBuffer_Error on + error (i.e. the object does not have a buffer interface or + it is not working). + + If fort is 'F' and the object is multi-dimensional, + then the data will be copied into the array in + Fortran-style (first dimension varies the fastest). If + fort is 'C', then the data will be copied into the array + in C-style (last dimension varies the fastest). If fort + is 'A', then it does not matter and the copy will be made + in whatever way is more efficient. + + */ + + PyAPI_FUNC(int) PyObject_CopyData(PyObject *dest, PyObject *src); + + /* Copy the data from the src buffer to the buffer of destination + */ + + PyAPI_FUNC(int) PyBuffer_IsContiguous(Py_buffer *view, char fort); + + + PyAPI_FUNC(void) PyBuffer_FillContiguousStrides(int ndims, + Py_ssize_t *shape, + Py_ssize_t *strides, + int itemsize, + char fort); + + /* Fill the strides array with byte-strides of a contiguous + (Fortran-style if fort is 'F' or C-style otherwise) + array of the given shape with the given number of bytes + per element. + */ + + PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, void *buf, + Py_ssize_t len, int readonly, + int flags); + + /* Fills in a buffer-info structure correctly for an exporter + that can only share a contiguous chunk of memory of + "unsigned bytes" of the given length. Returns 0 on success + and -1 (with raising an error) on error. + */ + PyAPI_FUNC(PyObject *) PyObject_Format(PyObject* obj, PyObject *format_spec); /* diff --git a/Include/object.h b/Include/object.h index 8d04935840b..bf0f62512ed 100644 --- a/Include/object.h +++ b/Include/object.h @@ -151,6 +151,8 @@ typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *); typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *); + + /* int-based buffer interface */ typedef int (*getreadbufferproc)(PyObject *, int, void **); typedef int (*getwritebufferproc)(PyObject *, int, void **); @@ -162,6 +164,67 @@ typedef Py_ssize_t (*writebufferproc)(PyObject *, Py_ssize_t, void **); typedef Py_ssize_t (*segcountproc)(PyObject *, Py_ssize_t *); typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **); +/* Py3k buffer interface */ + +typedef struct bufferinfo { + void *buf; + Py_ssize_t len; + Py_ssize_t itemsize; /* This is Py_ssize_t so it can be + pointed to by strides in simple case.*/ + int readonly; + int ndim; + char *format; + Py_ssize_t *shape; + Py_ssize_t *strides; + Py_ssize_t *suboffsets; + void *internal; +} Py_buffer; + +typedef int (*getbufferproc)(PyObject *, Py_buffer *, int); +typedef void (*releasebufferproc)(PyObject *, Py_buffer *); + + /* Flags for getting buffers */ +#define PyBUF_SIMPLE 0 +#define PyBUF_WRITABLE 0x0001 +/* we used to include an E, backwards compatible alias */ +#define PyBUF_WRITEABLE PyBUF_WRITABLE +#define PyBUF_LOCK 0x0002 +#define PyBUF_FORMAT 0x0004 +#define PyBUF_ND 0x0008 +#define PyBUF_STRIDES (0x0010 | PyBUF_ND) +#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) +#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) +#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) +#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) + +#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE) +#define PyBUF_CONTIG_RO (PyBUF_ND) +#define PyBUF_CONTIG_LCK (PyBUF_ND | PyBUF_LOCK) +#define PyBUF_CONTIG_XLCK (PyBUF_ND | PyBUF_LOCK | PyBUF_WRITABLE) + +#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE) +#define PyBUF_STRIDED_RO (PyBUF_STRIDES) +#define PyBUF_STRIDED_LCK (PyBUF_STRIDES | PyBUF_LOCK) +#define PyBUF_STRIDED_XLCK (PyBUF_STRIDES | PyBUF_LOCK | PyBUF_WRITABLE) + +#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT) +#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT) +#define PyBUF_RECORDS_LCK (PyBUF_STRIDES | PyBUF_LOCK | PyBUF_FORMAT) +#define PyBUF_RECORDS_XLCK (PyBUF_STRIDES | PyBUF_LOCK | PyBUF_WRITABLE \ + | PyBUF_FORMAT) + +#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT) +#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT) +#define PyBUF_FULL_LCK (PyBUF_INDIRECT | PyBUF_LOCK | PyBUF_FORMAT) +#define PyBUF_FULL_XLCK (PyBUF_INDIRECT | PyBUF_LOCK | PyBUF_WRITABLE \ + | PyBUF_FORMAT) + + +#define PyBUF_READ 0x100 +#define PyBUF_WRITE 0x200 +#define PyBUF_SHADOW 0x400 +/* end Py3k buffer interface */ + typedef int (*objobjproc)(PyObject *, PyObject *); typedef int (*visitproc)(PyObject *, void *); typedef int (*traverseproc)(PyObject *, visitproc, void *); @@ -247,6 +310,8 @@ typedef struct { writebufferproc bf_getwritebuffer; segcountproc bf_getsegcount; charbufferproc bf_getcharbuffer; + getbufferproc bf_getbuffer; + releasebufferproc bf_releasebuffer; } PyBufferProcs; @@ -540,6 +605,9 @@ given type object has a specified feature. /* Type is abstract and cannot be instantiated */ #define Py_TPFLAGS_IS_ABSTRACT (1L<<20) +/* Has the new buffer protocol */ +#define Py_TPFLAGS_HAVE_NEWBUFFER (1L<<21) + /* These flags are used to determine if a type is a subclass. */ #define Py_TPFLAGS_INT_SUBCLASS (1L<<23) #define Py_TPFLAGS_LONG_SUBCLASS (1L<<24) diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 73a0e36288b..9c2bc67dc34 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -160,6 +160,8 @@ PyAPI_DATA(PyObject *) PyExc_WindowsError; PyAPI_DATA(PyObject *) PyExc_VMSError; #endif +PyAPI_DATA(PyObject *) PyExc_BufferError; + PyAPI_DATA(PyObject *) PyExc_MemoryErrorInst; PyAPI_DATA(PyObject *) PyExc_RecursionErrorInst;