1 //-------------------------------------------------------------------------- 2 // Name: src/wxpybuffer.h 3 // Purpose: A simple class to hold a pointer and a size. See 4 // wxpybuffer.sip for code that converts from a Python buffer 5 // object as a MappedType. 6 // 7 // Author: Robin Dunn 8 // 9 // Created: 26-Apr-2012 10 // Copyright: (c) 2012-2018 by Total Control Software 11 // Licence: wxWindows license 12 //-------------------------------------------------------------------------- 13 14 #ifndef WXPYBUFFER_H 15 #define WXPYBUFFER_H 16 17 // TODO: When support for Python2 is dropped then look into changing this 18 // class such that it holds on to the Py_buffer view object for the lifetime of 19 // the wxPyBuffer object. This could help with cases where the buffer is 20 // attempted to be accessed when the source object has already been gc'd. 21 22 class wxPyBuffer 23 { 24 public: wxPyBuffer()25 wxPyBuffer() : m_ptr(NULL), m_len(0) {} 26 27 // Initialize this object's pointer and length from a PyObject supporting 28 // the Python buffer protocol. Raises a TypeError if the object can not 29 // be used as a buffer. create(PyObject * obj)30 bool create(PyObject* obj) { 31 #if PY_MAJOR_VERSION < 3 32 // Old buffer protocol 33 int rv = PyObject_AsReadBuffer(obj, (const void**)&m_ptr, &m_len); 34 return rv != -1; 35 #else 36 // New buffer protocol 37 Py_buffer view; 38 if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) 39 return false; 40 m_ptr = view.buf; 41 m_len = view.len; 42 PyBuffer_Release(&view); 43 return true; 44 #endif 45 } 46 47 48 // Ensure that the buffer's size is the expected size. Raises a 49 // Python ValueError exception and returns false if not. checkSize(Py_ssize_t expectedSize)50 bool checkSize(Py_ssize_t expectedSize) { 51 if (m_len < expectedSize) { 52 wxPyErr_SetString(PyExc_ValueError, "Invalid data buffer size."); 53 return false; 54 } 55 return true; 56 } 57 58 // Make a simple C copy of the data buffer. Malloc is used because 59 // the wxAPIs this is used with will later free() the pointer. Raises 60 // a Python exception if there is an allocation error. copy()61 void* copy() { 62 void* ptr = malloc(m_len); 63 if (ptr == NULL) { 64 wxPyBLOCK_THREADS(PyErr_NoMemory()); 65 return NULL; 66 } 67 memcpy(ptr, m_ptr, m_len); 68 return ptr; 69 } 70 71 void* m_ptr; 72 Py_ssize_t m_len; 73 }; 74 75 #endif 76 //-------------------------------------------------------------------------- 77