""" Utility for changing itemsize of memoryviews, and getting numpy arrays from byte-arrays that should be interpreted with a different itemsize. Authors ------- * MinRK """ #----------------------------------------------------------------------------- # Copyright (c) 2010-2012 Brian Granger, Min Ragan-Kelley # # This file is part of pyzmq # # Distributed under the terms of the New BSD License. The full license is in # the file COPYING.BSD, distributed as part of this software. #----------------------------------------------------------------------------- from libc.stdlib cimport malloc from buffers cimport * cdef inline object _rebuffer(object obj, char * format, int itemsize): """clobber the format & itemsize of a 1-D This is the Python 3 model, but will work on Python >= 2.6. Currently, we use it only on >= 3.0. """ cdef Py_buffer view cdef int flags = PyBUF_SIMPLE cdef int mode = 0 # cdef Py_ssize_t *shape, *strides, *suboffsets mode = check_buffer(obj) if mode == 0: raise TypeError("%r does not provide a buffer interface."%obj) if mode == 3: flags = PyBUF_ANY_CONTIGUOUS if format: flags |= PyBUF_FORMAT PyObject_GetBuffer(obj, &view, flags) assert view.ndim <= 1, "Can only reinterpret 1-D memoryviews" assert view.len % itemsize == 0, "Buffer of length %i not divisible into items of size %i"%(view.len, itemsize) # hack the format view.ndim = 1 view.format = format view.itemsize = itemsize view.strides = malloc(sizeof(Py_ssize_t)) view.strides[0] = itemsize view.shape = malloc(sizeof(Py_ssize_t)) view.shape[0] = view.len/itemsize view.suboffsets = malloc(sizeof(Py_ssize_t)) view.suboffsets[0] = 0 # for debug: make buffer writable, for zero-copy testing # view.readonly = 0 return PyMemoryView_FromBuffer(&view) else: raise TypeError("This funciton is only for new-style buffer objects.") def rebuffer(obj, format, itemsize): """Change the itemsize of a memoryview. Only for 1D contiguous buffers. """ return _rebuffer(obj, format, itemsize) def array_from_buffer(view, dtype, shape): """Get a numpy array from a memoryview, regardless of the itemsize of the original memoryview. This is important, because pyzmq does not send memoryview shape data over the wire, so we need to change the memoryview itemsize before calling asarray. """ import numpy A = numpy.array([],dtype=dtype) ref = viewfromobject(A,0) fmt = ref.format.encode() buf = viewfromobject(view, 0) buf = _rebuffer(view, fmt, ref.itemsize) return numpy.asarray(buf, dtype=dtype).reshape(shape) def print_view_info(obj): """simple utility for printing info on a new-style buffer object""" cdef Py_buffer view cdef int flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT cdef int mode = 0 mode = check_buffer(obj) if mode == 0: raise TypeError("%r does not provide a buffer interface."%obj) if mode == 3: PyObject_GetBuffer(obj, &view, flags) print view.buf, view.len, view.format, view.ndim, if view.ndim: if view.shape: print view.shape[0], if view.strides: print view.strides[0], if view.suboffsets: print view.suboffsets[0], print