diff options
author | Renaud Aubin <renaud.aubin@gmail.com> | 2019-05-27 22:17:44 +0200 |
---|---|---|
committer | Renaud Aubin <renaud.aubin@gmail.com> | 2019-06-05 19:32:44 +0200 |
commit | f7f12ba7f277d4c074382b5434123dc66b8791b8 (patch) | |
tree | 64c27f854d22abea1c8684c31f7b7ce1123e3f04 /sources | |
parent | f4d1a606a0fe5f15ea89779ca3f1bbb9673c2cc6 (diff) |
Implement the Buffer Protocol on VoidPtr
Some use cases need direct data access for performance,
e.g. initializing QPolygonF data with numpy.frombuffer. Implementing the
Buffer Protocol as described in PEP3118 will allow direct data
access.
Change-Id: I13c46055b1cba115d099f1becb64c4cd04acdf0e
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources')
-rw-r--r-- | sources/pyside2/tests/support/voidptr_test.py | 7 | ||||
-rw-r--r-- | sources/shiboken2/libshiboken/voidptr.cpp | 87 |
2 files changed, 91 insertions, 3 deletions
diff --git a/sources/pyside2/tests/support/voidptr_test.py b/sources/pyside2/tests/support/voidptr_test.py index c04022489..f68217244 100644 --- a/sources/pyside2/tests/support/voidptr_test.py +++ b/sources/pyside2/tests/support/voidptr_test.py @@ -54,6 +54,11 @@ class PySide2Support(unittest.TestCase): # Convert original and new to str self.assertTrue(str(b), str(nba)) + # Modify nba through a memoryview of vp + mv = memoryview(vp) + self.assertFalse(mv.readonly) + mv[6:11] = b'void*' + self.assertEqual(str(ba), str(b"Hello void*")) + if __name__ == '__main__': unittest.main() - diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp index e55ccfab5..5b0cb84ea 100644 --- a/sources/shiboken2/libshiboken/voidptr.cpp +++ b/sources/shiboken2/libshiboken/voidptr.cpp @@ -249,6 +249,83 @@ PyObject *SbkVoidPtrObject_str(PyObject *v) } +static int SbkVoidPtrObject_getbuffer(PyObject *obj, Py_buffer *view, int flags) +{ + if (view == NULL) + return -1; + + SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(obj); + if (sbkObject->size < 0) + return -1; + + int readonly = sbkObject->isWritable ? 0 : 1; + if (((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE) && + (readonly == 1)) { + PyErr_SetString(PyExc_BufferError, + "Object is not writable."); + return -1; + } + + view->obj = obj; + if (obj) + Py_XINCREF(obj); + view->buf = sbkObject->cptr; + view->len = sbkObject->size; + view->readonly = readonly; + view->itemsize = 1; + view->format = NULL; + if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) + view->format = "B"; + view->ndim = 1; + view->shape = NULL; + if ((flags & PyBUF_ND) == PyBUF_ND) + view->shape = &(view->len); + view->strides = NULL; + if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) + view->strides = &(view->itemsize); + view->suboffsets = NULL; + view->internal = NULL; + return 0; +} + +#if PY_VERSION_HEX < 0x03000000 + +static Py_ssize_t SbkVoidPtrObject_readbufferproc(PyObject* self, Py_ssize_t segment, void** ptrptr) +{ + if (segment || !Shiboken::Object::isValid(self)) + return -1; + + SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self); + *ptrptr = reinterpret_cast<void*>(sbkObject->cptr); + return sbkObject->size; +} + +static Py_ssize_t SbkVoidPtrObject_segcountproc(PyObject* self, Py_ssize_t* lenp) +{ + if (lenp) { + SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self); + *lenp = sbkObject->size; + } + return 1; +} + +PyBufferProcs SbkVoidPtrObjectBufferProc = { + &SbkVoidPtrObject_readbufferproc, // bf_getreadbuffer + (writebufferproc)&SbkVoidPtrObject_readbufferproc, // bf_getwritebuffer + &SbkVoidPtrObject_segcountproc, // bf_getsegcount + (charbufferproc)&SbkVoidPtrObject_readbufferproc, // bf_getcharbuffer + (getbufferproc)SbkVoidPtrObject_getbuffer, // bf_getbuffer +}; + +#else + +static PyBufferProcs SbkVoidPtrObjectBufferProc = { + (getbufferproc)SbkVoidPtrObject_getbuffer, // bf_getbuffer + (releasebufferproc)0 // bf_releasebuffer +}; + +#endif + // Void pointer type definition. static PyType_Slot SbkVoidPtrType_slots[] = { {Py_tp_repr, (void *)SbkVoidPtrObject_repr}, @@ -278,6 +355,14 @@ PyTypeObject *SbkVoidPtrTypeF(void) static PyTypeObject *type = nullptr; if (!type) type = (PyTypeObject *)PyType_FromSpec(&SbkVoidPtrType_spec); + +#if PY_VERSION_HEX < 0x03000000 + type->tp_as_buffer = &SbkVoidPtrObjectBufferProc; + type->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; +#else + PepType_AS_BUFFER(type) = &SbkVoidPtrObjectBufferProc; +#endif + return type; } @@ -394,5 +479,3 @@ SbkConverter *createConverter() } } // namespace VoidPtr - - |