summaryrefslogtreecommitdiff
path: root/numpy/core/src
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2009-12-06 12:04:47 +0000
committerPauli Virtanen <pav@iki.fi>2009-12-06 12:04:47 +0000
commit816035e8881f19437b7f1d08b30e48cf4adac278 (patch)
treeabc6b9b5442ab55c863e7ce60476836b8a74de79 /numpy/core/src
parent795b044cc36fbe63b681147767cf18e28ecf2b51 (diff)
downloadnumpy-816035e8881f19437b7f1d08b30e48cf4adac278.tar.gz
core: Implement the PEP 3118 buffer protocol (exporter part)
Also, use MemoryView instead of PyBuffer for Py3.
Diffstat (limited to 'numpy/core/src')
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src12
-rw-r--r--numpy/core/src/multiarray/buffer.c275
-rw-r--r--numpy/core/src/multiarray/common.c4
-rw-r--r--numpy/core/src/multiarray/conversion_utils.c6
-rw-r--r--numpy/core/src/multiarray/ctors.c25
-rw-r--r--numpy/core/src/multiarray/descriptor.c6
-rw-r--r--numpy/core/src/multiarray/getset.c12
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c29
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src68
9 files changed, 421 insertions, 16 deletions
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index 5971dd081..15a7cb86c 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -586,10 +586,22 @@ finish:
}
itemsize = ap->descr->elsize;
if (PyArray_ISWRITEABLE(ap)) {
+#if defined(NPY_PY3K)
+#warning XXX -- needs implementation
+ PyErr_SetString(PyExc_RuntimeError, "XXX -- not implemented");
+ u = NULL;
+#else
u = PyBuffer_FromReadWriteMemory(ip, itemsize);
+#endif
}
else {
+#if defined(NPY_PY3K)
+#warning XXX -- needs implementation
+ PyErr_SetString(PyExc_RuntimeError, "XXX -- not implemented");
+ u = NULL;
+#else
u = PyBuffer_FromMemory(ip, itemsize);
+#endif
}
if (u == NULL) {
goto fail;
diff --git a/numpy/core/src/multiarray/buffer.c b/numpy/core/src/multiarray/buffer.c
index 5cf5054bd..f94de4364 100644
--- a/numpy/core/src/multiarray/buffer.c
+++ b/numpy/core/src/multiarray/buffer.c
@@ -69,20 +69,287 @@ array_getcharbuf(PyArrayObject *self, Py_ssize_t segment, constchar **ptrptr)
return array_getreadbuf(self, segment, (void **) ptrptr);
}
+
+#if PY_VERSION_HEX >= 0x02060000
+
+/*
+ * Buffer protocol format string translator
+ */
+
+typedef struct {
+ char *s;
+ int allocated;
+ int pos;
+} _tmp_string;
+
+static int
+_append_char(_tmp_string *s, char c)
+{
+ char *p;
+ if (s->s == NULL) {
+ s->s = (char*)malloc(16);
+ s->pos = 0;
+ s->allocated = 16;
+ }
+ if (s->pos >= s->allocated) {
+ p = (char*)realloc(s->s, 2*s->allocated);
+ if (p == NULL) {
+ PyErr_SetString(PyExc_MemoryError, "memory allocation failed");
+ return -1;
+ }
+ s->s = p;
+ s->allocated *= 2;
+ }
+ s->s[s->pos] = c;
+ ++s->pos;
+ return 0;
+}
+
+static int
+_append_str(_tmp_string *s, char *c)
+{
+ while (*c != '\0') {
+ if (_append_char(s, *c)) return -1;
+ ++c;
+ }
+}
+
+static int
+_buffer_format_string(PyArray_Descr *descr, _tmp_string *str, int *offset)
+{
+ PyObject *s;
+ int k;
+ int zero_offset = 0;
+
+ if (descr->subarray) {
+ PyErr_SetString(PyExc_ValueError,
+ "data types with sub-arrays cannot be exported as "
+ "buffers");
+ return -1;
+ }
+ else if (PyDataType_HASFIELDS(descr)) {
+ _append_str(str, "T{");
+ for (k = 0; k < PyTuple_GET_SIZE(descr->names); ++k) {
+ PyObject *name, *item, *offset_obj, *tmp;
+ PyArray_Descr *child;
+ char *p;
+ Py_ssize_t len;
+ int new_offset;
+
+ name = PyTuple_GET_ITEM(descr->names, k);
+ item = PyDict_GetItem(descr->fields, name);
+
+ child = (PyArray_Descr*)PyTuple_GetItem(item, 0);
+ offset_obj = PyTuple_GetItem(item, 1);
+ new_offset = PyInt_AsLong(offset_obj);
+
+ /* Insert padding manually */
+ while (*offset < new_offset) {
+ _append_char(str, 'x');
+ ++*offset;
+ }
+ *offset += child->elsize;
+
+ /* Insert child item */
+ _buffer_format_string(child, str, offset);
+
+ /* Insert field name */
+#if defined(NPY_PY3K)
+#warning XXX -- should it use UTF-8 here?
+ tmp = PyUnicode_AsUTF8String(name);
+#else
+ tmp = name;
+#endif
+ if (tmp == NULL || PyBytes_AsStringAndSize(tmp, &p, &len) < 0) {
+ PyErr_SetString(PyExc_ValueError, "invalid field name");
+ return -1;
+ }
+ _append_char(str, ':');
+ while (len > 0) {
+ if (*p == ':') {
+ Py_DECREF(tmp);
+ PyErr_SetString(PyExc_ValueError,
+ "':' is not an allowed character in buffer "
+ "field names");
+ return -1;
+ }
+ _append_char(str, *p);
+ ++p;
+ --len;
+ }
+ _append_char(str, ':');
+#if defined(NPY_PY3K)
+ Py_DECREF(tmp);
+#endif
+ }
+ _append_char(str, '}');
+ }
+ else {
+ if (descr->byteorder == '<' || descr->byteorder == '>' ||
+ descr->byteorder == '=') {
+ _append_char(str, descr->byteorder);
+ }
+
+ switch (descr->type_num) {
+ case NPY_BYTE: if (_append_char(str, 'b')) return -1; break;
+ case NPY_UBYTE: if (_append_char(str, 'B')) return -1; break;
+ case NPY_SHORT: if (_append_char(str, 'h')) return -1; break;
+ case NPY_USHORT: if (_append_char(str, 'H')) return -1; break;
+ case NPY_INT: if (_append_char(str, 'i')) return -1; break;
+ case NPY_UINT: if (_append_char(str, 'I')) return -1; break;
+ case NPY_LONG: if (_append_char(str, 'l')) return -1; break;
+ case NPY_ULONG: if (_append_char(str, 'L')) return -1; break;
+ case NPY_LONGLONG: if (_append_char(str, 'q')) return -1; break;
+ case NPY_ULONGLONG: if (_append_char(str, 'Q')) return -1; break;
+ case NPY_FLOAT: if (_append_char(str, 'f')) return -1; break;
+ case NPY_DOUBLE: if (_append_char(str, 'd')) return -1; break;
+ case NPY_LONGDOUBLE: if (_append_char(str, 'g')) return -1; break;
+ case NPY_CFLOAT: if (_append_str(str, "Zf")) return -1; break;
+ case NPY_CDOUBLE: if (_append_str(str, "Zd")) return -1; break;
+ case NPY_CLONGDOUBLE: if (_append_str(str, "Zg")) return -1; break;
+ case NPY_STRING: {
+ char buf[128];
+ PyOS_snprintf(buf, sizeof(buf), "%ds", descr->elsize);
+ if (_append_str(str, buf)) return -1;
+ break;
+ }
+ case NPY_UNICODE: {
+ /* Numpy Unicode is always 4-byte */
+ char buf[128];
+ assert(descr->elsize % 4 == 0);
+ PyOS_snprintf(buf, sizeof(buf), "%dw", descr->elsize / 4);
+ if (_append_str(str, buf)) return -1;
+ break;
+ }
+ case NPY_OBJECT: if (_append_char(str, 'O')) return -1; break;
+ default:
+ PyErr_Format(PyExc_ValueError, "unknown dtype code %d",
+ descr->type_num);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * The new buffer protocol
+ */
+
+static int
+array_getbuffer(PyObject *self, Py_buffer *view, int flags)
+{
+ view->format = NULL;
+ view->shape = NULL;
+
+ if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS &&
+ !PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)) {
+ PyErr_SetString(PyExc_ValueError, "ndarray is not C contiguous");
+ goto fail;
+ }
+ if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS &&
+ !PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)) {
+ PyErr_SetString(PyExc_ValueError, "ndarray is not Fortran contiguous");
+ goto fail;
+ }
+ if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS
+ && !PyArray_ISONESEGMENT(self)) {
+ PyErr_SetString(PyExc_ValueError, "ndarray is not contiguous");
+ goto fail;
+ }
+
+ view->buf = PyArray_DATA(self);
+ view->suboffsets = NULL;
+ view->itemsize = PyArray_ITEMSIZE(self);
+ view->readonly = !PyArray_ISWRITEABLE(self);
+ view->internal = NULL;
+ view->len = PyArray_NBYTES(self);
+
+ if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
+ if (cache->format == NULL) {
+ int offset = 0;
+ _tmp_string fmt = {0,0,0};
+ if (_buffer_format_string(PyArray_DESCR(self), &fmt, &offset)) {
+ goto fail;
+ }
+ _append_char(&fmt, '\0');
+ cache->format = fmt.s;
+ }
+ _append_char(&fmt, '\0');
+ view->format = fmt.s;
+ }
+ else {
+ view->format = NULL;
+ }
+
+ if ((flags & PyBUF_STRIDED) == PyBUF_STRIDED) {
+ int k;
+ view->ndim = PyArray_NDIM(self);
+ view->shape = (Py_ssize_t*)malloc(sizeof(Py_ssize_t) * view->ndim * 2);
+ view->strides = view->shape + view->ndim;
+ for (k = 0; k < PyArray_NDIM(self); ++k) {
+ view->shape[k] = PyArray_DIMS(self)[k];
+ view->strides[k] = PyArray_STRIDES(self)[k];
+ }
+ }
+ else if (PyArray_ISONESEGMENT(self)) {
+#warning XXX -- should try harder here to determine single-segmentness?
+ view->ndim = 0;
+ view->shape = NULL;
+ view->strides = NULL;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError, "ndarray is not single-segment");
+ goto fail;
+ }
+
+ view->obj = self;
+ Py_INCREF(self);
+
+ return 0;
+
+fail:
+ if (view->format) {
+ free(view->format);
+ }
+ if (view->shape) {
+ free(view->shape);
+ }
+ return -1;
+}
+
+static void
+array_releasebuffer(PyObject *self, Py_buffer *view)
+{
+ if (view->format != NULL) {
+ free(view->format);
+ view->format = NULL;
+ }
+ if (view->shape != NULL) {
+ free(view->shape);
+ view->shape = NULL;
+ }
+}
+
+#endif
+
+
NPY_NO_EXPORT PyBufferProcs array_as_buffer = {
+#if !defined(NPY_PY3K)
#if PY_VERSION_HEX >= 0x02050000
(readbufferproc)array_getreadbuf, /*bf_getreadbuffer*/
(writebufferproc)array_getwritebuf, /*bf_getwritebuffer*/
(segcountproc)array_getsegcount, /*bf_getsegcount*/
(charbufferproc)array_getcharbuf, /*bf_getcharbuffer*/
-#if PY_VERSION_HEX >= 0x02060000
- (getbufferproc)0,
- (releasebufferproc)0,
-#endif
#else
(getreadbufferproc)array_getreadbuf, /*bf_getreadbuffer*/
(getwritebufferproc)array_getwritebuf, /*bf_getwritebuffer*/
(getsegcountproc)array_getsegcount, /*bf_getsegcount*/
(getcharbufferproc)array_getcharbuf, /*bf_getcharbuffer*/
#endif
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+ (getbufferproc)array_getbuffer,
+ (releasebufferproc)array_releasebuffer,
+#endif
};
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 7eec15396..f76e61460 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -243,7 +243,11 @@ _array_find_type(PyObject *op, PyArray_Descr *minitype, int max)
goto finish;
}
+#if defined(NPY_PY3K)
+ if (PyMemoryView_Check(op)) {
+#else
if (PyBuffer_Check(op)) {
+#endif
chktype = PyArray_DescrNewFromType(PyArray_VOID);
chktype->elsize = Py_TYPE(op)->tp_as_sequence->sq_length(op);
PyErr_Clear();
diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c
index 2d507e316..b6b72464e 100644
--- a/numpy/core/src/multiarray/conversion_utils.c
+++ b/numpy/core/src/multiarray/conversion_utils.c
@@ -158,9 +158,15 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
buf->len = (intp) buflen;
/* Point to the base of the buffer object if present */
+#if defined(NPY_PY3K)
+ if (PyMemoryView_Check(obj)) {
+ buf->base = PyMemoryView_GET_BASE(obj);
+ }
+#else
if (PyBuffer_Check(obj)) {
buf->base = ((PyArray_Chunk *)obj)->base;
}
+#endif
if (buf->base == NULL) {
buf->base = obj;
}
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 075662599..80f010e8f 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -1103,7 +1103,13 @@ discover_depth(PyObject *s, int max, int stop_at_string, int stop_at_tuple)
if (PyArray_IsScalar(s, Generic)) {
return 0;
}
- if (PyString_Check(s) || PyBuffer_Check(s) || PyUnicode_Check(s)) {
+ if (PyString_Check(s) ||
+#if defined(NPY_PY3K)
+ PyMemoryView_Check(s) ||
+#else
+ PyBuffer_Check(s) ||
+#endif
+ PyUnicode_Check(s)) {
return stop_at_string ? 0:1;
}
if (stop_at_tuple && PyTuple_Check(s)) {
@@ -1171,7 +1177,13 @@ discover_itemsize(PyObject *s, int nd, int *itemsize)
n = PyObject_Length(s);
if ((nd == 0) || PyString_Check(s) ||
- PyUnicode_Check(s) || PyBuffer_Check(s)) {
+#if defined(NPY_PY3K)
+ PyMemoryView_Check(s) ||
+#else
+ PyBuffer_Check(s) ||
+#endif
+ PyUnicode_Check(s)) {
+
*itemsize = MAX(*itemsize, n);
return 0;
}
@@ -3071,8 +3083,13 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
return NULL;
}
if (Py_TYPE(buf)->tp_as_buffer == NULL
+#if defined(NPY_PY3K)
+ || Py_TYPE(buf)->tp_as_buffer->bf_getbuffer == NULL
+#else
|| (Py_TYPE(buf)->tp_as_buffer->bf_getwritebuffer == NULL
- && Py_TYPE(buf)->tp_as_buffer->bf_getreadbuffer == NULL)) {
+ && Py_TYPE(buf)->tp_as_buffer->bf_getreadbuffer == NULL)
+#endif
+ ) {
PyObject *newbuf;
newbuf = PyObject_GetAttrString(buf, "__buffer__");
if (newbuf == NULL) {
@@ -3085,6 +3102,8 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
Py_INCREF(buf);
}
+#warning XXX: Should implement support for the new buffer interface here!
+
if (PyObject_AsWriteBuffer(buf, (void *)&data, &ts) == -1) {
write = 0;
PyErr_Clear();
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 77d998f2b..b9fbd4175 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1149,9 +1149,15 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at)
else if (obj == (PyObject *)(&PyUnicode_Type)) {
check_num = PyArray_UNICODE;
}
+#if defined(NPY_PY3K)
+ else if (obj == (PyObject *)(&PyMemoryView_Type)) {
+ check_num = PyArray_VOID;
+ }
+#else
else if (obj == (PyObject *)(&PyBuffer_Type)) {
check_num = PyArray_VOID;
}
+#endif
else {
*at = _arraydescr_fromobj(obj);
if (*at) {
diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c
index b0364d2d2..3f397a557 100644
--- a/numpy/core/src/multiarray/getset.c
+++ b/numpy/core/src/multiarray/getset.c
@@ -279,6 +279,9 @@ array_interface_get(PyArrayObject *self)
static PyObject *
array_data_get(PyArrayObject *self)
{
+#if defined(NPY_PY3K)
+ return PyMemoryView_FromObject(self);
+#else
intp nbytes;
if (!(PyArray_ISONESEGMENT(self))) {
PyErr_SetString(PyExc_AttributeError, "cannot get single-"\
@@ -286,17 +289,23 @@ array_data_get(PyArrayObject *self)
return NULL;
}
nbytes = PyArray_NBYTES(self);
- if PyArray_ISWRITEABLE(self) {
+ if (PyArray_ISWRITEABLE(self)) {
return PyBuffer_FromReadWriteObject((PyObject *)self, 0, (Py_ssize_t) nbytes);
}
else {
return PyBuffer_FromObject((PyObject *)self, 0, (Py_ssize_t) nbytes);
}
+#endif
}
static int
array_data_set(PyArrayObject *self, PyObject *op)
{
+#if defined(NPY_PY3K)
+#warning XXX -- need to implement this
+ PyErr_SetString(PyExc_RuntimeError, "XXX -- not implemented");
+ return -1;
+#else
void *buf;
Py_ssize_t buf_len;
int writeable=1;
@@ -338,6 +347,7 @@ array_data_set(PyArrayObject *self, PyObject *op)
self->flags &= ~WRITEABLE;
}
return 0;
+#endif
}
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 95d233538..430058e37 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -2138,14 +2138,25 @@ new_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args)
if(!PyArg_ParseTuple(args, "i", &size)) {
return NULL;
}
+#if defined(NPY_PY3K)
+#warning XXX -- needs to implement this?
+ PyErr_SetString(PyExc_RuntimeError, "XXX -- not implemented");
+ return NULL;
+#else
return PyBuffer_New(size);
+#endif
}
static PyObject *
buffer_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
{
PyObject *obj;
- Py_ssize_t offset = 0, size = Py_END_OF_BUFFER, n;
+ Py_ssize_t offset = 0, n;
+#if defined(NPY_PY3K)
+ Py_ssize_t size;
+#else
+ Py_ssize_t size = Py_END_OF_BUFFER;
+#endif
void *unused;
static char *kwlist[] = {"object", "offset", "size", NULL};
@@ -2156,10 +2167,20 @@ buffer_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
}
if (PyObject_AsWriteBuffer(obj, &unused, &n) < 0) {
PyErr_Clear();
+#if defined(NPY_PY3K)
+#warning XXX: should use the full memoryview capabilities
+ return PyMemoryView_FromObject(obj);
+#else
return PyBuffer_FromObject(obj, offset, size);
+#endif
}
else {
+#if defined(NPY_PY3K)
+#warning XXX: should use the full memoryview capabilities
+ return PyMemoryView_FromObject(obj);
+#else
return PyBuffer_FromReadWriteObject(obj, offset, size);
+#endif
}
}
@@ -2242,10 +2263,16 @@ as_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
}
+#if defined(NPY_PY3K)
+ PyErr_SetString(PyExc_RuntimeError,
+ "XXX -- not implemented!")
+ return NULL;
+#else
if (ro) {
return PyBuffer_FromMemory(memptr, size);
}
return PyBuffer_FromReadWriteMemory(memptr, size);
+#endif
}
#undef _test_code
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index 55b615989..e51c29ab9 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -772,7 +772,11 @@ voidtype_dtypedescr_get(PyVoidScalarObject *self)
static PyObject *
gentype_data_get(PyObject *self)
{
+#if defined(NPY_PY3K)
+ return PyMemoryView_FromObject(self);
+#else
return PyBuffer_FromObject(self, 0, Py_END_OF_BUFFER);
+#endif
}
@@ -1812,7 +1816,6 @@ static PySequenceMethods voidtype_as_sequence = {
};
-
static Py_ssize_t
gentype_getreadbuf(PyObject *self, Py_ssize_t segment, void **ptrptr)
{
@@ -1871,15 +1874,34 @@ gentype_getcharbuf(PyObject *self, Py_ssize_t segment, constchar **ptrptr)
}
}
+#if PY_VERSION_HEX >= 0x02060000
+
+static int
+gentype_getbuffer(PyObject *self, Py_buffer *view, int flags)
+{
+ Py_ssize_t len;
+ void *buf;
+
+#warning XXX: the format is not implemented! -- this needs more work
+
+ len = gentype_getreadbuf(self, 0, &buf);
+ return PyBuffer_FillInfo(view, self, buf, len, 1, flags);
+}
+
+/* releasebuffer is not needed */
+
+#endif
static PyBufferProcs gentype_as_buffer = {
+#if !defined(NPY_PY3K)
gentype_getreadbuf, /* bf_getreadbuffer*/
NULL, /* bf_getwritebuffer*/
gentype_getsegcount, /* bf_getsegcount*/
gentype_getcharbuf, /* bf_getcharbuffer*/
+#endif
#if PY_VERSION_HEX >= 0x02060000
- NULL,
- NULL,
+ gentype_getbuffer, /* bf_getbuffer */
+ NULL, /* bf_releasebuffer */
#endif
};
@@ -2635,6 +2657,7 @@ static PyMappingMethods object_arrtype_as_mapping = {
#endif
};
+#if !defined(NPY_PY3K)
static Py_ssize_t
object_arrtype_getsegcount(PyObjectScalarObject *self, Py_ssize_t *lenp)
{
@@ -2698,23 +2721,54 @@ object_arrtype_getcharbuf(PyObjectScalarObject *self, Py_ssize_t segment,
}
return (*pb->bf_getcharbuffer)(self->obval, segment, ptrptr);
}
+#endif
+
+#if PY_VERSION_HEX >= 0x02060000
+static int
+object_arrtype_getbuffer(PyObjectScalarObject *self, Py_buffer *view, int flags)
+{
+ PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer;
+ if (pb == NULL || pb->bf_getbuffer == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "expected a readable buffer object");
+ return -1;
+ }
+ return (*pb->bf_getbuffer)(self->obval, view, flags);
+}
+
+static void
+object_arrtype_releasebuffer(PyObjectScalarObject *self, Py_buffer *view)
+{
+ PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer;
+ if (pb == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "expected a readable buffer object");
+ return;
+ }
+ if (pb->bf_releasebuffer != NULL) {
+ (*pb->bf_releasebuffer)(self->obval, view);
+ }
+}
+#endif
static PyBufferProcs object_arrtype_as_buffer = {
+#if !defined(NPY_PY3K)
#if PY_VERSION_HEX >= 0x02050000
(readbufferproc)object_arrtype_getreadbuf,
(writebufferproc)object_arrtype_getwritebuf,
(segcountproc)object_arrtype_getsegcount,
(charbufferproc)object_arrtype_getcharbuf,
-#if PY_VERSION_HEX >= 0x02060000
- (getbufferproc)0,
- (releasebufferproc)0,
-#endif
#else
(getreadbufferproc)object_arrtype_getreadbuf,
(getwritebufferproc)object_arrtype_getwritebuf,
(getsegcountproc)object_arrtype_getsegcount,
(getcharbufferproc)object_arrtype_getcharbuf,
#endif
+#endif
+#if PY_VERSION_HEX >= 0x02060000
+ (getbufferproc)object_arrtype_getbuffer,
+ (releasebufferproc)object_arrtype_releasebuffer,
+#endif
};
static PyObject *