ArrayStruct_and_Pyrex - SciPy wiki dump (original) (raw)
Overview
Pyrex is a language for writing C extensions to Python. Its syntax is very similar to writing Python. A .pyx file is compiled to a .c file, which is then compiled like a standard C extension module for Python. Many people find writing extension modules with Pyrex preferable to writing them in C or using other tools, such as SWIG.
See http://numeric.scipy.org/ for an explanation of the __array_struct__ interface. The following packages support the interface:
- NumPy (all versions)
- Numeric (>=24.2)
- numarray (>=1.5.0)
Sharing data malloced by a Pyrex-based extension
Here is a Pyrex file which shows how to export its data using the __array_struct__ array interface. This allows various Python types to have a view of the data without actually copying the data itself.
cdef extern from "Python.h": ctypedef int Py_intptr_t void Py_INCREF(object) void Py_DECREF(object) object PyCObject_FromVoidPtrAndDesc( void* cobj, void* desc, void (*destr)(void *, void *))
cdef extern from "stdlib.h": ctypedef int size_t ctypedef long intptr_t void malloc(size_t size) void free(void ptr)
CONTIGUOUS=0x01 FORTRAN=0x02 ALIGNED=0x100 NOTSWAPPED=0x200 WRITEABLE=0x400
ctypedef struct PyArrayInterface:
int version
int nd
char typekind
int itemsize
int flags
Py_intptr_t *shape
Py_intptr_t *strides
void *data
cdef void free_array_interface( void* ptr, void arr ): cdef PyArrayInterface inter
inter = <PyArrayInterface*>ptr
arrpy = <object>arr
Py_DECREF( arrpy )
free(inter)
ctypedef unsigned char fi ctypedef fi* fiptr cdef class Unsigned8Buf: cdef fiptr data cdef Py_intptr_t shape[2] cdef Py_intptr_t strides[2]
def __init__(self, int width, int height):
cdef int bufsize
bufsize = width*height*sizeof(fi)
self.data=<fiptr>malloc( bufsize )
if self.data==NULL: raise MemoryError("Error allocating memory")
self.strides[0]=width
self.strides[1]=1
self.shape[0]=height
self.shape[1]=width
def __dealloc__(self):
free(self.data)
property __array_struct__:
def __get__(self):
cdef PyArrayInterface* inter
cdef Py_intptr_t *newshape
cdef Py_intptr_t *newstrides
cdef int nd
nd = 2
inter = <PyArrayInterface*>malloc( sizeof( PyArrayInterface ) )
if inter is NULL:
raise MemoryError()
inter.version = 2
inter.nd = nd
inter.typekind = 'u'[0]
inter.itemsize = 1
inter.flags = NOTSWAPPED | ALIGNED | WRITEABLE
inter.strides = self.strides
inter.shape = self.shape
inter.data = self.data
Py_INCREF(self)
obj = PyCObject_FromVoidPtrAndDesc( <void*>inter, <void*>self, free_array_interface)
return obj
Using data malloced elsewhere with a Pyrex-based extension
One example is the get_data_copy() function of _cam_iface_shm.pyx in the motmot camera utilities software. In this use example, an image is copied from shared memory into an externally malloced buffer supporting the __array_struct__ interface. (The shared memory stuff has only been tested on linux, but the rest should work anywhere.)
See also
SciPy: Cookbook/ArrayStruct_and_Pyrex (last edited 2015-10-24 17:48:23 by anonymous)