diff options
author | Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> | 2019-02-27 16:54:31 +0100 |
---|---|---|
committer | Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> | 2019-03-15 16:47:46 +0000 |
commit | 45e3c96a8075d210b70eabdb2ef9c3f7f1ca17af (patch) | |
tree | 640e32355745259489fabcf7834c599cf717178d /sources/shiboken2/libshiboken | |
parent | 264f7fccaffa79d947b872a8179993ef547e069c (diff) |
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 <qt_ci_bot@qt-project.org>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'sources/shiboken2/libshiboken')
-rw-r--r-- | sources/shiboken2/libshiboken/voidptr.cpp | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/sources/shiboken2/libshiboken/voidptr.cpp b/sources/shiboken2/libshiboken/voidptr.cpp index a306f7a9d..e55ccfab5 100644 --- a/sources/shiboken2/libshiboken/voidptr.cpp +++ b/sources/shiboken2/libshiboken/voidptr.cpp @@ -95,13 +95,6 @@ int SbkVoidPtrObject_init(PyObject *self, PyObject *args, PyObject *kwds) sbkSelf->size = sbkOther->size; sbkSelf->isWritable = sbkOther->isWritable; } - // Shiboken::Object wrapper. - else if (Shiboken::Object::checkType(addressObject)) { - SbkObject *sbkOther = reinterpret_cast<SbkObject *>(addressObject); - sbkSelf->cptr = sbkOther->d->cptr[0]; - sbkSelf->size = size; - sbkSelf->isWritable = isWritable > 0 ? true : false; - } // Python buffer interface. else if (PyObject_CheckBuffer(addressObject)) { Py_buffer bufferView; @@ -111,26 +104,41 @@ int SbkVoidPtrObject_init(PyObject *self, PyObject *args, PyObject *kwds) return 0; sbkSelf->cptr = bufferView.buf; - sbkSelf->size = bufferView.len; + sbkSelf->size = bufferView.len > 0 ? bufferView.len : size; sbkSelf->isWritable = bufferView.readonly > 0 ? false : true; // Release the buffer. PyBuffer_Release(&bufferView); } + // Shiboken::Object wrapper. + else if (Shiboken::Object::checkType(addressObject)) { + SbkObject *sbkOther = reinterpret_cast<SbkObject *>(addressObject); + sbkSelf->cptr = sbkOther->d->cptr[0]; + sbkSelf->size = size; + sbkSelf->isWritable = isWritable > 0 ? true : false; + } // An integer representing an address. else { - void *cptr = PyLong_AsVoidPtr(addressObject); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "Creating a VoidPtr object requires an address of a C++ object, " - "a wrapped Shiboken Object type, " - "an object implementing the Python Buffer interface, " - "or another VoidPtr object."); - return -1; + if (addressObject == Py_None) { + sbkSelf->cptr = nullptr; + sbkSelf->size = 0; + sbkSelf->isWritable = false; + } + + else { + void *cptr = PyLong_AsVoidPtr(addressObject); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "Creating a VoidPtr object requires an address of a C++ object, " + "a wrapped Shiboken Object type, " + "an object implementing the Python Buffer interface, " + "or another VoidPtr object."); + return -1; + } + sbkSelf->cptr = cptr; + sbkSelf->size = size; + sbkSelf->isWritable = isWritable > 0 ? true : false; } - sbkSelf->cptr = cptr; - sbkSelf->size = size; - sbkSelf->isWritable = isWritable > 0 ? true : false; } return 0; @@ -174,6 +182,24 @@ PyObject *SbkVoidPtrObject_int(PyObject *v) return PyLong_FromVoidPtr(sbkObject->cptr); } +PyObject *toBytes(PyObject *self, PyObject *args) +{ + SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self); + if (sbkObject->size < 0) { + PyErr_SetString(PyExc_IndexError, "VoidPtr does not have a size set."); + return nullptr; + } + PyObject *bytes = PyBytes_FromStringAndSize(reinterpret_cast<const char*>(sbkObject->cptr), + sbkObject->size); + Py_XINCREF(bytes); + return bytes; +} + +static struct PyMethodDef SbkVoidPtrObject_methods[] = { + {"toBytes", toBytes, METH_NOARGS}, + {0} +}; + static Py_ssize_t SbkVoidPtrObject_length(PyObject *v) { SbkVoidPtrObject *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(v); @@ -233,6 +259,7 @@ static PyType_Slot SbkVoidPtrType_slots[] = { {Py_tp_init, (void *)SbkVoidPtrObject_init}, {Py_tp_new, (void *)SbkVoidPtrObject_new}, {Py_tp_dealloc, (void *)object_dealloc}, + {Py_tp_methods, (void *)SbkVoidPtrObject_methods}, {0, 0} }; static PyType_Spec SbkVoidPtrType_spec = { |