[Pyrex] Passing objects back to Python?

Glenn grpython at sonic.net
Sat Feb 3 19:38:47 UTC 2007


Hi,

I have a Python program (finding the thicknesses in a multilayer  
optical thin film stack) that works well, but it's too slow. I  
decided to test the waters
of using Pyrex to speed up the compute intensive part of the program.

What I want to do is pass ndarrays from Python to a compiled library  
I've written and get an array and scalar returned. I found cookbook  
examples for the
first part, which access and print out array elements. Those seem to  
work fine.

The problem occurs when I try to pass an object back to Python.

Here is the contents my c_python.pxd file:


> cdef extern from "Python.h":
>     ctypedef int Py_intptr_t

And my c_numpy.pxd:

> cdef extern from "numpy/arrayobject.h":
>
>     ctypedef int npy_intp
>     #
>     #struct PyArray_Descr:
>     #    int type_num, elsize
>     #    char type
>     ##
>     ctypedef extern class numpy.dtype [object PyArray_Descr]:
>         cdef int type_num, elsize, alignment
>         cdef char type, kind, byteorder, hasobject
>         cdef object fields, typeobj
>
>     ctypedef extern class numpy.ndarray [object PyArrayObject]:
>         cdef char *data
>         cdef int nd
>         cdef npy_intp *dimensions
>         cdef npy_intp *strides
>         cdef object base
>         cdef dtype descr
>         cdef int flags
>
>
>
>     cdef void import_array()
>

The main file, ftest.pyx is


> cimport c_python
> cimport c_numpy
> import numpy
>
> # Numpy/C API array pointer must be initialized
> c_numpy.import_array()
>
> def scale_array(c_numpy.ndarray arr):
>     print type(arr),"= type(arr)"
>     #print type(<c_python.Py_intptr_t>arr.strides),"= type 
> (arr.strides)"
>
>     els = []
>     for i from 0<=i<arr.dimensions[0]:
>         print '  ',10.0*(<double*>arr.data)[0]
>         els.append((<double*>arr.data)[0])
>         arr.data = arr.data + arr.strides[0]
>     return els

ftest.c is generated just fine by distutils and built and installed.  
When I fire up Python in a shell and execute the scale_array()  
function, at first things appear OK:

> >>> import ftest
> >>> import numpy
> >>> inarr = numpy.array([1.1,2.2,3.3])
> >>> inarr
> array([ 1.1,  2.2,  3.3])
> >>> ftest.scale_array(inarr)
> <type 'numpy.ndarray'> = type(arr)
>    11.0
>    22.0
>    33.0
> [1.1000000000000001, 2.2000000000000002, 3.2999999999999998]

but something is very, very wrong. If I now test the value of inarr I  
get:

> >>> inarr
> array([  8.51149973e-096,   9.81872068e-308,   3.23795802e-319])

Apparently, execution of the library function overwrote an area of  
memory that it shouldn't have. What have I done wrong? Can someone  
give me a pointer to a tested example of how to properly pass Python  
objects from an extension back to Python?

As I read the Pyrex materials, I thought I was in relatively shallow  
waters, but now it appears I'm in way over my head.

Regards,

Glenn






More information about the Pyrex mailing list