summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c/_cffi_backend.c9
-rw-r--r--c/cffi1_module.c3
-rw-r--r--c/ffi_obj.c14
-rw-r--r--c/minibuffer.h32
-rw-r--r--c/test_c.py1
-rw-r--r--cffi/api.py25
-rw-r--r--doc/source/ref.rst7
-rw-r--r--doc/source/whatsnew.rst3
-rw-r--r--testing/cffi0/backend_tests.py1
-rw-r--r--testing/cffi1/test_ffi_obj.py1
10 files changed, 67 insertions, 29 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index 7d763ff..d9aaf6e 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -6029,8 +6029,10 @@ static PyObject *b_unpack(PyObject *self, PyObject *args, PyObject *kwds)
return result;
}
-static PyObject *b_buffer(PyObject *self, PyObject *args, PyObject *kwds)
+static PyObject *
+b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
+ /* this is the constructor of the type implemented in minibuffer.h */
CDataObject *cd;
Py_ssize_t size = -1;
static char *keywords[] = {"cdata", "size", NULL};
@@ -6655,7 +6657,6 @@ static PyMethodDef FFIBackendMethods[] = {
{"getcname", b_getcname, METH_VARARGS},
{"string", (PyCFunction)b_string, METH_VARARGS | METH_KEYWORDS},
{"unpack", (PyCFunction)b_unpack, METH_VARARGS | METH_KEYWORDS},
- {"buffer", (PyCFunction)b_buffer, METH_VARARGS | METH_KEYWORDS},
{"get_errno", b_get_errno, METH_NOARGS},
{"set_errno", b_set_errno, METH_O},
{"newp_handle", b_newp_handle, METH_VARARGS},
@@ -6959,6 +6960,10 @@ init_cffi_backend(void)
INITERROR;
}
+ Py_INCREF(&MiniBuffer_Type);
+ if (PyModule_AddObject(m, "buffer", (PyObject *)&MiniBuffer_Type) < 0)
+ INITERROR;
+
init_cffi_tls();
if (PyErr_Occurred())
INITERROR;
diff --git a/c/cffi1_module.c b/c/cffi1_module.c
index bf309f6..8776262 100644
--- a/c/cffi1_module.c
+++ b/c/cffi1_module.c
@@ -45,6 +45,9 @@ static int init_ffi_lib(PyObject *m)
if (PyDict_SetItemString(FFI_Type.tp_dict, "CData",
(PyObject *)&CData_Type) < 0)
return -1;
+ if (PyDict_SetItemString(FFI_Type.tp_dict, "buffer",
+ (PyObject *)&MiniBuffer_Type) < 0)
+ return -1;
for (i = 0; all_dlopen_flags[i].name != NULL; i++) {
x = PyInt_FromLong(all_dlopen_flags[i].value);
diff --git a/c/ffi_obj.c b/c/ffi_obj.c
index 3c4866e..103f175 100644
--- a/c/ffi_obj.c
+++ b/c/ffi_obj.c
@@ -475,19 +475,6 @@ PyDoc_STRVAR(ffi_unpack_doc,
#define ffi_unpack b_unpack /* ffi_unpack() => b_unpack()
from _cffi_backend.c */
-PyDoc_STRVAR(ffi_buffer_doc,
-"Return a read-write buffer object that references the raw C data\n"
-"pointed to by the given 'cdata'. The 'cdata' must be a pointer or an\n"
-"array. Can be passed to functions expecting a buffer, or directly\n"
-"manipulated with:\n"
-"\n"
-" buf[:] get a copy of it in a regular string, or\n"
-" buf[idx] as a single character\n"
-" buf[:] = ...\n"
-" buf[idx] = ... change the content");
-
-#define ffi_buffer b_buffer /* ffi_buffer() => b_buffer()
- from _cffi_backend.c */
PyDoc_STRVAR(ffi_offsetof_doc,
"Return the offset of the named field inside the given structure or\n"
@@ -1085,7 +1072,6 @@ static PyObject *ffi_init_once(FFIObject *self, PyObject *args, PyObject *kwds)
static PyMethodDef ffi_methods[] = {
{"addressof", (PyCFunction)ffi_addressof, METH_VARARGS, ffi_addressof_doc},
{"alignof", (PyCFunction)ffi_alignof, METH_O, ffi_alignof_doc},
- {"buffer", (PyCFunction)ffi_buffer, METH_VKW, ffi_buffer_doc},
{"def_extern", (PyCFunction)ffi_def_extern, METH_VKW, ffi_def_extern_doc},
{"callback", (PyCFunction)ffi_callback, METH_VKW, ffi_callback_doc},
{"cast", (PyCFunction)ffi_cast, METH_VARARGS, ffi_cast_doc},
diff --git a/c/minibuffer.h b/c/minibuffer.h
index 92cf079..6cce3e1 100644
--- a/c/minibuffer.h
+++ b/c/minibuffer.h
@@ -238,6 +238,22 @@ static PyMappingMethods mb_as_mapping = {
# define MINIBUF_TPFLAGS (Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_NEWBUFFER)
#endif
+PyDoc_STRVAR(ffi_buffer_doc,
+"ffi.buffer(cdata):\n"
+"Return a read-write buffer object that references the raw C data\n"
+"pointed to by the given 'cdata'. The 'cdata' must be a pointer or an\n"
+"array. Can be passed to functions expecting a buffer, or directly\n"
+"manipulated with:\n"
+"\n"
+" buf[:] get a copy of it in a regular string, or\n"
+" buf[idx] as a single character\n"
+" buf[:] = ...\n"
+" buf[idx] = ... change the content");
+
+static PyObject * /* forward, implemented in _cffi_backend.c */
+b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+
+
static PyTypeObject MiniBuffer_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_cffi_backend.buffer",
@@ -268,11 +284,25 @@ static PyTypeObject MiniBuffer_Type = {
&mb_as_buffer, /* tp_as_buffer */
(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
MINIBUF_TPFLAGS), /* tp_flags */
- 0, /* tp_doc */
+ ffi_buffer_doc, /* tp_doc */
(traverseproc)mb_traverse, /* tp_traverse */
(inquiry)mb_clear, /* tp_clear */
0, /* tp_richcompare */
offsetof(MiniBufferObj, mb_weakreflist), /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ b_buffer_new, /* tp_new */
+ 0, /* tp_free */
};
static PyObject *minibuffer_new(char *data, Py_ssize_t size,
diff --git a/c/test_c.py b/c/test_c.py
index fdc14ef..79c6fce 100644
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2299,6 +2299,7 @@ def test_buffer():
buf = buffer(c)
assert repr(buf).startswith('<_cffi_backend.buffer object at 0x')
assert bytes(buf) == b"hi there\x00"
+ assert type(buf) is buffer
if sys.version_info < (3,):
assert str(buf) == "hi there\x00"
assert unicode(buf) == u+"hi there\x00"
diff --git a/cffi/api.py b/cffi/api.py
index 43b78f8..272a6a7 100644
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -93,6 +93,7 @@ class FFI(object):
# ctypes backend: attach these constants to the instance
self.NULL = self.cast(self.BVoidP, 0)
self.CData, self.CType = backend._get_types()
+ self.buffer = backend.buffer
def cdef(self, csource, override=False, packed=False):
"""Parse the given C source. This registers all declared functions,
@@ -316,18 +317,18 @@ class FFI(object):
"""
return self._backend.unpack(cdata, length)
- def buffer(self, cdata, size=-1):
- """Return a read-write buffer object that references the raw C data
- pointed to by the given 'cdata'. The 'cdata' must be a pointer or
- an array. Can be passed to functions expecting a buffer, or directly
- manipulated with:
-
- buf[:] get a copy of it in a regular string, or
- buf[idx] as a single character
- buf[:] = ...
- buf[idx] = ... change the content
- """
- return self._backend.buffer(cdata, size)
+ #def buffer(self, cdata, size=-1):
+ # """Return a read-write buffer object that references the raw C data
+ # pointed to by the given 'cdata'. The 'cdata' must be a pointer or
+ # an array. Can be passed to functions expecting a buffer, or directly
+ # manipulated with:
+ #
+ # buf[:] get a copy of it in a regular string, or
+ # buf[idx] as a single character
+ # buf[:] = ...
+ # buf[idx] = ... change the content
+ # """
+ # note that 'buffer' is a type, set on this instance by __init__
def from_buffer(self, python_buffer):
"""Return a <cdata 'char[]'> that points to the data of the
diff --git a/doc/source/ref.rst b/doc/source/ref.rst
index 9b5f8c9..dd99625 100644
--- a/doc/source/ref.rst
+++ b/doc/source/ref.rst
@@ -172,6 +172,9 @@ because it gives inconsistent results between Python 2 and Python 3.
(This is similar to how ``str()`` gives inconsistent results on regular
byte strings). Use ``buf[:]`` instead.
+*New in version 1.10:* ``ffi.buffer`` is now the type of the returned
+buffer objects; ``ffi.buffer()`` actually calls the constructor.
+
**ffi.from_buffer(python_buffer)**: return a ``<cdata 'char[]'>`` that
points to the data of the given Python object, which must support the
buffer interface. This is the opposite of ``ffi.buffer()``. It gives
@@ -334,6 +337,10 @@ always present, and depending on the kind they may also have
``item``, ``length``, ``fields``, ``args``, ``result``, ``ellipsis``,
``abi``, ``elements`` and ``relements``.
+*New in version 1.10:* ``ffi.buffer`` is now `a type`__ as well.
+
+.. __: #ffi-buffer
+
ffi.gc()
++++++++
diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst
index edc0b50..9db3b96 100644
--- a/doc/source/whatsnew.rst
+++ b/doc/source/whatsnew.rst
@@ -43,6 +43,9 @@ v1.10
aside, ``ffi.string()`` no longer works on ``_Bool[]`` (but it never
made much sense, as this function stops on the first zero).
+* ``ffi.buffer`` is now the name of cffi's buffer type, and
+ ``ffi.buffer()`` works like before but is the constructor of that type.
+
v1.9
====
diff --git a/testing/cffi0/backend_tests.py b/testing/cffi0/backend_tests.py
index 0a771ac..8eb279d 100644
--- a/testing/cffi0/backend_tests.py
+++ b/testing/cffi0/backend_tests.py
@@ -1130,6 +1130,7 @@ class BackendTests:
b = ffi.buffer(a)
except NotImplementedError as e:
py.test.skip(str(e))
+ assert type(b) is ffi.buffer
content = b[:]
assert len(content) == len(b) == 2
if sys.byteorder == 'little':
diff --git a/testing/cffi1/test_ffi_obj.py b/testing/cffi1/test_ffi_obj.py
index 4415115..2b5d764 100644
--- a/testing/cffi1/test_ffi_obj.py
+++ b/testing/cffi1/test_ffi_obj.py
@@ -233,6 +233,7 @@ def test_ffi_buffer():
a = ffi.new("signed char[]", [5, 6, 7])
assert ffi.buffer(a)[:] == b'\x05\x06\x07'
assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06'
+ assert type(ffi.buffer(a)) is ffi.buffer
def test_ffi_from_buffer():
import array