[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