static void Bitmap_setPixels(Bitmap& bitmap, PyObject* exporter) { Py_buffer bufferView; // PyObject_Print(PyObject_Type(exporter), stderr, 0); if (PyObject_CheckBuffer(exporter)) { PyObject_GetBuffer(exporter, &bufferView, PyBUF_READ); const unsigned char* pBuf = reinterpret_cast<unsigned char*>(bufferView.buf); bitmap.setPixels(pBuf); PyBuffer_Release(&bufferView); } else if (PyBuffer_Check(exporter)) { PyTypeObject * pType = exporter->ob_type; PyBufferProcs * pProcs = pType->tp_as_buffer; AVG_ASSERT(pProcs); Py_ssize_t numBytes; Py_ssize_t numSegments = pProcs->bf_getsegcount(exporter, &numBytes); if (numBytes != bitmap.getMemNeeded()) { throw Exception(AVG_ERR_INVALID_ARGS, "Second parameter to Bitmap.setPixels must fit bitmap size."); } // TODO: check if bitmap size is correct unsigned char* pDestPixels = bitmap.getPixels(); for (unsigned i=0; i<numSegments; ++i) { void* pSrcPixels; long bytesInSegment = pProcs->bf_getreadbuffer(exporter, i, &pSrcPixels); memcpy(pDestPixels, pSrcPixels, bytesInSegment); pDestPixels += bytesInSegment; } } else { throw Exception(AVG_ERR_INVALID_ARGS, "Second parameter to Bitmap.setPixels must support the buffer interface."); } }
Py_ssize_t PyBuffer_GetMemory(PyObject* buffer, const char** pp) { PyBufferProcs* procs = buffer->ob_type->tp_as_buffer; if (!procs || !PyType_HasFeature(buffer->ob_type, Py_TPFLAGS_HAVE_GETCHARBUFFER)) { // Can't access the memory directly because the buffer object doesn't support it. return -1; } if (procs->bf_getsegcount(buffer, 0) != 1) { // Can't access the memory directly because there is more than one segment. return -1; } #if PY_VERSION_HEX >= 0x02050000 char* pT = 0; #else const char* pT = 0; #endif Py_ssize_t cb = procs->bf_getcharbuffer(buffer, 0, &pT); if (pp) *pp = pT; return cb; }
static int _read_from_handle(void *wasread, const int length, void *handle) { PyObject *py_handle = (PyObject *)handle, *py_retval = NULL; void *retval; int success = 0; PyBufferProcs *buffer; int segment; int bytes_read, bytes_left; if(!length) { PyErr_SetString(PyExc_RuntimeError, "data length is zero"); goto _read_from_handle_cleanup; } if(!(py_retval = PyObject_CallMethod(py_handle, "read", "i", length))) goto _read_from_handle_cleanup; if(!py_retval->ob_type->tp_as_buffer) { PyErr_SetString(PyExc_ValueError, "read method should return buffer"); goto _read_from_handle_cleanup; } if(!(py_retval->ob_type->tp_flags & Py_TPFLAGS_DEFAULT)) { PyErr_SetString(PyExc_ValueError, "no bf_getcharbuffer slot"); goto _read_from_handle_cleanup; } buffer = py_retval->ob_type->tp_as_buffer; if(!buffer->bf_getreadbuffer) { PyErr_SetString(PyExc_ValueError, "no bf_getreadbuffer"); goto _read_from_handle_cleanup; } bytes_left = length; segment = 0; while(bytes_left > 0) { if((bytes_read = buffer->bf_getreadbuffer(py_retval, segment, &retval)) == -1) { PyErr_SetString(PyExc_ValueError, "failed to read from buffer"); goto _read_from_handle_cleanup; } memcpy(wasread, retval, bytes_read); wasread = (void *)((char *)wasread + bytes_read); bytes_left -= bytes_read; segment += 1; } success = 1; _read_from_handle_cleanup: if(py_retval) { Py_DECREF(py_retval); } return success; }
static Py_ssize_t get_buffer(PyObject *obj, unsigned char **buf_p, PyObject **tmp_obj_p) { PyBufferProcs *bfp; PyObject *str = NULL; Py_ssize_t res; /* check for None */ if (obj == Py_None) { PyErr_Format(PyExc_TypeError, "None is not allowed"); return -1; } /* is string or unicode ? */ if (PyString_Check(obj) || PyUnicode_Check(obj)) { if (PyString_AsStringAndSize(obj, (char**)buf_p, &res) < 0) return -1; return res; } /* try to get buffer */ bfp = obj->ob_type->tp_as_buffer; if (bfp && bfp->bf_getsegcount && bfp->bf_getreadbuffer) { if (bfp->bf_getsegcount(obj, NULL) == 1) return bfp->bf_getreadbuffer(obj, 0, (void**)buf_p); } /* * Not a string-like object, run str() or it. */ /* are we in recursion? */ if (tmp_obj_p == NULL) { PyErr_Format(PyExc_TypeError, "Cannot convert to string - get_buffer() recusively failed"); return -1; } /* do str() then */ str = PyObject_Str(obj); res = -1; if (str != NULL) { res = get_buffer(str, buf_p, NULL); if (res >= 0) { *tmp_obj_p = str; } else { Py_CLEAR(str); } } return res; }
static Py_ssize_t _getbuffer(PyObject *obj, Py_buffer *view) { PyBufferProcs *buffer = Py_TYPE(obj)->tp_as_buffer; if (buffer == NULL || buffer->bf_getbuffer == NULL) { PyErr_Format(PyExc_TypeError, "Type %.100s doesn't support the buffer API", Py_TYPE(obj)->tp_name); return -1; } if (buffer->bf_getbuffer(obj, view, PyBUF_SIMPLE) < 0) return -1; return view->len; }
static launch_data_t python2launch(PyObject* object) { launch_data_t result; if (PyDict_Check(object)) { /* PyMapping_Check doesn't work because a lot of sequence types * are mappings as wel to support extended slices a[i:j:k] */ return pythondict2launch(object); } else if (PySequence_Check(object)) { return pythonarray2launch(object); } else if (PyInt_Check(object)) { long value = PyInt_AsLong(object); result = launch_data_alloc(LAUNCH_DATA_INTEGER); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_integer(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if (PyLong_Check(object)) { long long value = PyLong_AsLongLong(object); result = launch_data_alloc(LAUNCH_DATA_INTEGER); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_integer(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if (PyString_Check(object)) { char* value = PyString_AsString(object); result = launch_data_alloc(LAUNCH_DATA_STRING); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_string(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if ((PyObject*)(object->ob_type) == file_descriptor_type) { long value = PyInt_AsLong(object); result = launch_data_alloc(LAUNCH_DATA_FD); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_fd(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if ((PyObject*)(object->ob_type) == errno_type) { long value = PyInt_AsLong(object); result = launch_data_alloc(LAUNCH_DATA_ERRNO); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_errno(result, value)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else if (object->ob_type->tp_as_buffer != NULL) { PyBufferProcs* bp = object->ob_type->tp_as_buffer; void* ptr; size_t size; size = bp->bf_getreadbuffer(object, 0, &ptr); if (size == (size_t)-1) { return NULL; } result = launch_data_alloc(LAUNCH_DATA_OPAQUE); if (result == NULL) { PyErr_SetString(PyExc_TypeError, "allocating launch_data_t failed"); return NULL; } if (!launch_data_set_opaque(result, ptr, size)) { PyErr_SetString(PyExc_TypeError, "setting launch_data_t failed"); launch_data_free(result); return NULL; } } else { PyErr_Format(PyExc_TypeError, "Don't know how to convert object of type %s to launch", object->ob_type->tp_name); return NULL; } }
// Convert the Python values to a raw array. static void *convert_values(Array *array, PyObject *values, GLenum gl_type, sipErrorState *estate) { #if PY_VERSION_HEX >= 0x02060300 int rc = sipGetBufferInfo(values, &array->buffer); if (rc < 0) { *estate = sipErrorFail; return 0; } if (rc > 0) { // Check the buffer is compatible with what we need. GLenum array_type; switch (*array->buffer.bi_format) { case 'b': array_type = GL_BYTE; break; case 'B': array_type = GL_UNSIGNED_BYTE; break; case 'h': array_type = GL_SHORT; break; case 'H': array_type = GL_UNSIGNED_SHORT; break; case 'i': array_type = GL_INT; break; case 'I': array_type = GL_UNSIGNED_INT; break; case 'f': array_type = GL_FLOAT; break; #if defined(SIP_FEATURE_PyQt_Desktop_OpenGL) case 'd': array_type = GL_DOUBLE; break; #endif default: PyErr_Format(PyExc_TypeError, "unsupported buffer type '%s'", array->buffer.bi_format); *estate = sipErrorFail; return 0; } if (array_type != gl_type) { PyErr_SetString(PyExc_TypeError, "the buffer type is not the same as the array type"); *estate = sipErrorFail; return 0; } return array->buffer.bi_buf; } #else PyBufferProcs *bf = Py_TYPE(values)->tp_as_buffer; if (bf && bf->bf_getreadbuffer && bf->bf_getsegcount) { if (bf->bf_getsegcount(values, 0) != 1) { PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected"); *estate = sipErrorFail; return 0; } if (bf->bf_getreadbuffer(values, 0, reinterpret_cast<void **>(&array)) < 0) { *estate = sipErrorFail; return 0; } Py_INCREF(values); array->buffer = values; return array; } #endif PyObject *seq = PySequence_Fast(values, "array must be a sequence or a buffer"); if (!seq) { *estate = sipErrorContinue; return 0; } Py_ssize_t nr_items = Sequence_Fast_Size(seq); if (nr_items < 1) { Py_DECREF(seq); PyErr_SetString(PyExc_TypeError, "array must have at least one element"); *estate = sipErrorFail; return 0; } void (*convertor)(PyObject *, void *, Py_ssize_t); size_t element_size; switch (gl_type) { case GL_BYTE: convertor = convert_byte; element_size = sizeof (GLbyte); break; case GL_UNSIGNED_BYTE: convertor = convert_ubyte; element_size = sizeof (GLubyte); break; case GL_SHORT: convertor = convert_short; element_size = sizeof (GLshort); break; case GL_UNSIGNED_SHORT: convertor = convert_ushort; element_size = sizeof (GLushort); break; case GL_INT: convertor = convert_int; element_size = sizeof (GLint); break; case GL_UNSIGNED_INT: convertor = convert_uint; element_size = sizeof (GLuint); break; case GL_FLOAT: convertor = convert_float; element_size = sizeof (GLfloat); break; #if defined(SIP_FEATURE_PyQt_Desktop_OpenGL) #if GL_DOUBLE != GL_FLOAT case GL_DOUBLE: convertor = convert_double; element_size = sizeof (GLdouble); break; #endif #endif default: Py_DECREF(seq); PyErr_SetString(PyExc_TypeError, "unsupported GL element type"); *estate = sipErrorFail; return 0; } void *data = sipMalloc(nr_items * element_size); if (!data) { Py_DECREF(seq); *estate = sipErrorFail; return 0; } for (Py_ssize_t i = 0; i < nr_items; ++i) { PyErr_Clear(); convertor(Sequence_Fast_GetItem(seq, i), data, i); if (PyErr_Occurred()) { sipFree(data); Py_DECREF(seq); *estate = sipErrorFail; return 0; } } Py_DECREF(seq); array->data = data; return data; }