From 45e3c96a8075d210b70eabdb2ef9c3f7f1ca17af Mon Sep 17 00:00:00 2001 From: Cristian Maureira-Fredes Date: Wed, 27 Feb 2019 16:54:31 +0100 Subject: Add toBytes() and BufferProtocol VoidPtr: Add toBytes() method that return a char* representation of the void* pointer. QByteArray: The current implementation only provided the Buffer Protocol for Python2, this patch includes the getbuffer implementation for Python3. Having a BufferProtocol implementation for Python3 allows the initialization of VoidPtr to get access to the internal content, so one can go back and forward with the representation of it: ba = QByteArray(b"Hello World") vp = VoidPtr(ba, ba.size()) vp.toBytes() # b"Hello World" The BufferProtocol was also changed for Python2 including the new buffer protocol (Py_TPFLAGS_HAVE_NEWBUFFER) function `bf_getbuffer`. A test case was included. Fixes: PYSIDE-934 Change-Id: I8936966da91b2dcc879c582cfc35e6a35f7a60b6 Reviewed-by: Qt CI Bot Reviewed-by: Alexandru Croitor --- sources/pyside2/PySide2/glue/qtcore.cpp | 46 +++++++++++++++++++++++---- sources/pyside2/tests/support/voidptr_test.py | 18 +++++++++-- 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'sources/pyside2') diff --git a/sources/pyside2/PySide2/glue/qtcore.cpp b/sources/pyside2/PySide2/glue/qtcore.cpp index 629484458..6259724c3 100644 --- a/sources/pyside2/PySide2/glue/qtcore.cpp +++ b/sources/pyside2/PySide2/glue/qtcore.cpp @@ -965,13 +965,33 @@ if (PyIndex_Check(_key)) { // @snippet qbytearray-msetitem // @snippet qbytearray-bufferprotocol -#if PY_VERSION_HEX < 0x03000000 - +extern "C" { // QByteArray buffer protocol functions // see: http://www.python.org/dev/peps/pep-3118/ -extern "C" { +static int SbkQByteArray_getbufferproc(PyObject* obj, Py_buffer *view, int flags) +{ + if (!view || !Shiboken::Object::isValid(obj)) + return -1; + + QByteArray* cppSelf = %CONVERTTOCPP[QByteArray*](obj); + view->obj = obj; + view->buf = reinterpret_cast(cppSelf->data()); + view->len = cppSelf->size(); + view->readonly = 0; + view->itemsize = 1; + view->format = const_cast("c"); + view->ndim = 1; + view->shape = NULL; + view->strides = &view->itemsize; + view->suboffsets = NULL; + view->internal = NULL; + + Py_XINCREF(obj); + return 0; +} +#if PY_VERSION_HEX < 0x03000000 static Py_ssize_t SbkQByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp) { if (lenp) @@ -993,12 +1013,18 @@ PyBufferProcs SbkQByteArrayBufferProc = { /*bf_getreadbuffer*/ &SbkQByteArray_readbufferproc, /*bf_getwritebuffer*/ (writebufferproc) &SbkQByteArray_readbufferproc, /*bf_getsegcount*/ &SbkQByteArray_segcountproc, - /*bf_getcharbuffer*/ (charbufferproc) &SbkQByteArray_readbufferproc + /*bf_getcharbuffer*/ (charbufferproc) &SbkQByteArray_readbufferproc, + /*bf_getbuffer*/ (getbufferproc)SbkQByteArray_getbufferproc, }; +#else -} +static PyBufferProcs SbkQByteArrayBufferProc = { + /*bf_getbuffer*/ (getbufferproc)SbkQByteArray_getbufferproc, + /*bf_releasebuffer*/ (releasebufferproc)0, +}; #endif +} // @snippet qbytearray-bufferprotocol // @snippet qbytearray-operatorplus-1 @@ -1110,8 +1136,14 @@ if (PyBytes_Check(%PYARG_1)) { // @snippet qbytearray-py3 #if PY_VERSION_HEX < 0x03000000 - Shiboken::SbkType()->tp_as_buffer = &SbkQByteArrayBufferProc; - Shiboken::SbkType()->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER; +Shiboken::SbkType()->tp_as_buffer = &SbkQByteArrayBufferProc; +Shiboken::SbkType()->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; +#else +#ifdef Py_LIMITED_API +PepType_AS_BUFFER(Shiboken::SbkType()) = &SbkQByteArrayBufferProc; +#else +Shiboken::SbkType()->tp_as_buffer = &SbkQByteArrayBufferProc; +#endif #endif // @snippet qbytearray-py3 diff --git a/sources/pyside2/tests/support/voidptr_test.py b/sources/pyside2/tests/support/voidptr_test.py index 330788c63..c04022489 100644 --- a/sources/pyside2/tests/support/voidptr_test.py +++ b/sources/pyside2/tests/support/voidptr_test.py @@ -38,9 +38,21 @@ class PySide2Support(unittest.TestCase): # a C++ object, a wrapped Shiboken Object type, # an object implementing the Python Buffer interface, # or another VoidPtr object. - ba = QByteArray(b"Hello world") - voidptr = VoidPtr(ba) - self.assertIsInstance(voidptr, shiboken.VoidPtr) + + # Original content + b = b"Hello world" + ba = QByteArray(b) + vp = VoidPtr(ba, ba.size()) + self.assertIsInstance(vp, shiboken.VoidPtr) + + # Create QByteArray from voidptr byte interpretation + nba = QByteArray.fromRawData(vp.toBytes()) + # Compare original bytes to toBytes() + self.assertTrue(b, vp.toBytes()) + # Compare original with new QByteArray data + self.assertTrue(b, nba.data()) + # Convert original and new to str + self.assertTrue(str(b), str(nba)) if __name__ == '__main__': unittest.main() -- cgit v1.2.3