bpo-45459: Add Py_buffer to limited API (GH-29991)

- [x] ``Py_buffer`` struct
- [x] ``PyBuffer_*()`` API functions
- [x] ``PyBUF_*`` constants
- [x] ``Py_bf_getbuffer`` and ``Py_bf_releasebuffer`` type slots
- [x] ``PyMemoryView_FromBuffer()`` API
- [x] tests for limited API
- [x] ``make regen-limited-abi``
- [x] documentation update
- [ ] export ``PyPickleBuffer*()`` API ???
This commit is contained in:
Christian Heimes 2022-02-02 17:03:10 +02:00 committed by GitHub
parent 08f8301b21
commit f66c857572
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 308 additions and 131 deletions

View file

@ -19,6 +19,7 @@
def __init__(self):
# In the C class, "_x_attr" is not accessible from Python code
self._x_attr = {}
self._x_exports = 0
def __getattr__(self, name):
return self._x_attr[name]
@ -29,6 +30,13 @@
def __delattr__(self, name):
del self._x_attr[name]
@property
def x_exports(self):
"""Return the number of times an internal buffer is exported."""
# Each Xxo instance has a 10-byte buffer that can be
# accessed via the buffer interface (e.g. `memoryview`).
return self._x_exports
def demo(o, /):
if isinstance(o, str):
return o
@ -57,6 +65,9 @@
#define Py_LIMITED_API 0x030b0000
#include "Python.h"
#include <string.h>
#define BUFSIZE 10
// Module state
typedef struct {
@ -70,7 +81,9 @@ typedef struct {
// Instance state
typedef struct {
PyObject_HEAD
PyObject *x_attr; /* Attributes dictionary */
PyObject *x_attr; /* Attributes dictionary */
char x_buffer[BUFSIZE]; /* buffer for Py_buffer */
Py_ssize_t x_exports; /* how many buffer are exported */
} XxoObject;
// XXX: no good way to do this yet
@ -89,6 +102,8 @@ newXxoObject(PyObject *module)
return NULL;
}
self->x_attr = NULL;
memset(self->x_buffer, 0, BUFSIZE);
self->x_exports = 0;
return self;
}
@ -212,11 +227,43 @@ static PyMethodDef Xxo_methods[] = {
{NULL, NULL} /* sentinel */
};
/* Xxo buffer interface */
static int
Xxo_getbuffer(XxoObject *self, Py_buffer *view, int flags)
{
int res = PyBuffer_FillInfo(view, (PyObject*)self,
(void *)self->x_buffer, BUFSIZE,
0, flags);
if (res == 0) {
self->x_exports++;
}
return res;
}
static void
Xxo_releasebuffer(XxoObject *self, Py_buffer *view)
{
self->x_exports--;
}
static PyObject *
Xxo_get_x_exports(XxoObject *self, void *c)
{
return PyLong_FromSsize_t(self->x_exports);
}
/* Xxo type definition */
PyDoc_STRVAR(Xxo_doc,
"A class that explicitly stores attributes in an internal dict");
static PyGetSetDef Xxo_getsetlist[] = {
{"x_exports", (getter) Xxo_get_x_exports, NULL, NULL},
{NULL},
};
static PyType_Slot Xxo_Type_slots[] = {
{Py_tp_doc, (char *)Xxo_doc},
{Py_tp_traverse, Xxo_traverse},
@ -226,6 +273,9 @@ static PyType_Slot Xxo_Type_slots[] = {
{Py_tp_getattro, Xxo_getattro},
{Py_tp_setattro, Xxo_setattro},
{Py_tp_methods, Xxo_methods},
{Py_bf_getbuffer, Xxo_getbuffer},
{Py_bf_releasebuffer, Xxo_releasebuffer},
{Py_tp_getset, Xxo_getsetlist},
{0, 0}, /* sentinel */
};