diff options
author | Armin Rigo <arigo@tunes.org> | 2018-12-16 08:48:45 +0100 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2018-12-16 08:48:45 +0100 |
commit | d1320b79e38ee16d73c9e9c72fd0e5112cffbad8 (patch) | |
tree | 0f665aaa89b988ca533e1eaac6f31005b92e6bd8 /c | |
parent | cef175a37f0f15d87d61ddefa09664c19ce544da (diff) | |
download | cffi-d1320b79e38ee16d73c9e9c72fd0e5112cffbad8.tar.gz |
Issue #394
Implement ffi.from_buffer(x, require_writable=True)
Diffstat (limited to 'c')
-rw-r--r-- | c/_cffi_backend.c | 11 | ||||
-rw-r--r-- | c/ffi_obj.c | 13 | ||||
-rw-r--r-- | c/test_c.py | 12 |
3 files changed, 29 insertions, 7 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c index dc13c61..c6190e7 100644 --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -6741,7 +6741,8 @@ static int _my_PyObject_GetContiguousBuffer(PyObject *x, Py_buffer *view, return 0; } -static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x) +static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x, + int require_writable) { CDataObject *cd; Py_buffer *view; @@ -6761,7 +6762,7 @@ static PyObject *direct_from_buffer(CTypeDescrObject *ct, PyObject *x) PyErr_NoMemory(); return NULL; } - if (_my_PyObject_GetContiguousBuffer(x, view, 0) < 0) + if (_my_PyObject_GetContiguousBuffer(x, view, require_writable) < 0) goto error1; cd = (CDataObject *)PyObject_GC_New(CDataObject_owngc_frombuf, @@ -6789,15 +6790,17 @@ static PyObject *b_from_buffer(PyObject *self, PyObject *args) { CTypeDescrObject *ct; PyObject *x; + int require_writable = 0; - if (!PyArg_ParseTuple(args, "O!O", &CTypeDescr_Type, &ct, &x)) + if (!PyArg_ParseTuple(args, "O!O|i", &CTypeDescr_Type, &ct, &x, + &require_writable)) return NULL; if (!(ct->ct_flags & CT_IS_UNSIZED_CHAR_A)) { PyErr_Format(PyExc_TypeError, "needs 'char[]', got '%s'", ct->ct_name); return NULL; } - return direct_from_buffer(ct, x); + return direct_from_buffer(ct, x, require_writable); } static int _fetch_as_buffer(PyObject *x, Py_buffer *view, int writable_only) diff --git a/c/ffi_obj.c b/c/ffi_obj.c index 9e67466..cc5c715 100644 --- a/c/ffi_obj.c +++ b/c/ffi_obj.c @@ -697,9 +697,16 @@ PyDoc_STRVAR(ffi_from_buffer_doc, "containing large quantities of raw data in some other format, like\n" "'array.array' or numpy arrays."); -static PyObject *ffi_from_buffer(PyObject *self, PyObject *arg) +static PyObject *ffi_from_buffer(PyObject *self, PyObject *args, PyObject *kwds) { - return direct_from_buffer(g_ct_chararray, arg); + PyObject *arg; + int require_writable = 0; + static char *keywords[] = {"python_buffer", "require_writable", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:from_buffer", keywords, + &arg, &require_writable)) + return NULL; + return direct_from_buffer(g_ct_chararray, arg, require_writable); } PyDoc_STRVAR(ffi_gc_doc, @@ -1072,7 +1079,7 @@ static PyMethodDef ffi_methods[] = { {"cast", (PyCFunction)ffi_cast, METH_VARARGS, ffi_cast_doc}, {"dlclose", (PyCFunction)ffi_dlclose, METH_VARARGS, ffi_dlclose_doc}, {"dlopen", (PyCFunction)ffi_dlopen, METH_VARARGS, ffi_dlopen_doc}, - {"from_buffer",(PyCFunction)ffi_from_buffer,METH_O, ffi_from_buffer_doc}, + {"from_buffer",(PyCFunction)ffi_from_buffer,METH_VKW, ffi_from_buffer_doc}, {"from_handle",(PyCFunction)ffi_from_handle,METH_O, ffi_from_handle_doc}, {"gc", (PyCFunction)ffi_gc, METH_VKW, ffi_gc_doc}, {"getctype", (PyCFunction)ffi_getctype, METH_VKW, ffi_getctype_doc}, diff --git a/c/test_c.py b/c/test_c.py index b83c0aa..b6bb752 100644 --- a/c/test_c.py +++ b/c/test_c.py @@ -3741,6 +3741,18 @@ def test_from_buffer_more_cases(): check(4 | 8, "CHB", "GTB") check(4 | 16, "CHB", "ROB") +def test_from_buffer_require_writable(): + BChar = new_primitive_type("char") + BCharP = new_pointer_type(BChar) + BCharA = new_array_type(BCharP, None) + p1 = from_buffer(BCharA, b"foo", False) + assert p1 == from_buffer(BCharA, b"foo", False) + py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True) + ba = bytearray(b"foo") + p1 = from_buffer(BCharA, ba, True) + p1[0] = b"g" + assert ba == b"goo" + def test_memmove(): Short = new_primitive_type("short") ShortA = new_array_type(new_pointer_type(Short), None) |