getting data pointer to numpy object in Pyrex

Hello,
I posted this on the Pyrex list, but I figured someone here may be able to answer it too.
Is here an easy way, in Pyrex, to get the data pointer to a numpy object which is *not* passed as a parameter? For example, I know I can do:
#--------------- cdef extern from "numpy/arrayobject.h":
struct PyArray_Descr: int type_num, elsize char type
ctypedef class numpy.ArrayType [object PyArrayObject]: cdef char *data cdef int nd cdef int *dimensions, *strides cdef object base cdef PyArray_Descr *descr cdef int flags
def test1(ArrayType w): # pass a numpy object
cdef double *w_p
# get the pointers w_p=<double *>w.data #---------------
...but I would like to do something like...
#------------------------------- def test2(d): # pass a python dict
w=d['w'] # get the numpy object
cdef double *w_p
# get the pointers w_p=<double *>w.data #-------------------------------
Is there a way to do this?
thanks,
Brian Blais

Brian Blais wrote:
Hello,
I posted this on the Pyrex list, but I figured someone here may be able to answer it too.
Is here an easy way, in Pyrex, to get the data pointer to a numpy object which is *not* passed as a parameter? For example, I know I can do:
#--------------- cdef extern from "numpy/arrayobject.h":
struct PyArray_Descr: int type_num, elsize char type
ctypedef class numpy.ArrayType [object PyArrayObject]: cdef char *data cdef int nd cdef int *dimensions, *strides cdef object base cdef PyArray_Descr *descr cdef int flags
def test1(ArrayType w): # pass a numpy object
cdef double *w_p # get the pointers w_p=<double *>w.data
#---------------
...but I would like to do something like...
#------------------------------- def test2(d): # pass a python dict
w=d['w'] # get the numpy object cdef double *w_p # get the pointers w_p=<double *>w.data
#-------------------------------
Is there a way to do this?
You will probably want to use the c_numpy.pxd file in numpy/doc/pyrex/. It has exposed a bit more of the API than you have. If you have any contributions, we would like to fold them in.
In general, you would just make a cast like you would for any other C type. However, you must be sure that the object actually is an array. I think the following code would work as expected, including the case where d['w'] can't be turned into an array, but I have not tested it.
cimport c_numpy import numpy
c_numpy.import_array()
def test2(d): cdef c_numpy.ndarray w
w = <c_numpy.ndarray>numpy.asarray(d['w']) # ...

Robert Kern wrote:
Brian Blais wrote:
Is here an easy way, in Pyrex, to get the data pointer to a numpy object which is *not* passed as a parameter? For example, I know I can do:
You will probably want to use the c_numpy.pxd file in numpy/doc/pyrex/. It has exposed a bit more of the API than you have. If you have any contributions, we would like to fold them in.
In general, you would just make a cast like you would for any other C type. However, you must be sure that the object actually is an array. I think the following code would work as expected, including the case where d['w'] can't be turned into an array, but I have not tested it.
cimport c_numpy import numpy
c_numpy.import_array()
def test2(d): cdef c_numpy.ndarray w
w = <c_numpy.ndarray>numpy.asarray(d['w']) # ...
I tried this, and got some warnings, and the code didn't work. I get the compile-time warning of:
warning: use of cast expressions as lvalues is deprecated
(along with all of the other, normal, Pyrex compile warnings)
I am including the code here:
#test3.pyx cimport c_numpy import numpy c_numpy.import_array()
cdef extern from "numpy/arrayobject.h":
struct PyArray_Descr: int type_num, elsize char type
ctypedef class numpy.ArrayType [object PyArrayObject]: cdef char *data cdef int nd cdef int *dimensions, *strides cdef object base cdef PyArray_Descr *descr cdef int flags
def fun1(d):
cdef ArrayType W cdef double *w cdef int i,l
W=d['w'] w=<double *>W.data l=W.dimensions[0]*W.dimensions[1]
for i from 0 <= i < l:
print "%.4e" % w[i]
def fun2(d): cdef c_numpy.ndarray W cdef double *w cdef int i,l
W = <c_numpy.ndarray>numpy.asarray(d['w']) w=<double *>W.data l=W.dimensions[0]*W.dimensions[1]
for i from 0 <= i < l:
print "%.4e" % w[i]
#=================================================
#run_test3.py import numpy import test3
w=numpy.arange(0,2,.5) d={"w":w}
test3.fun1(d)
print "==================="
test3.fun2(d)
#===================================================
#output from program:
execfile('run_test3.py')
0.0000e+00 5.0000e-01 1.0000e+00 1.5000e+00 8.3394e-312 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 1.9354e+01 5.3216e-315 0.0000e+00 2.1127e+01 5.3428e-315 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 -5.1923e+00 2.5548e+02 =================== 0.0000e+00 5.0000e-01 1.0000e+00 1.5000e+00 8.3394e-312 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 1.9354e+01 5.3216e-315 0.0000e+00 2.1127e+01 5.3428e-315 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 0.0000e+00 -5.1923e+00 2.5548e+02

A Dimecres 29 Març 2006 00:28, Brian Blais va escriure:
...but I would like to do something like...
#------------------------------- def test2(d): # pass a python dict
w=d['w'] # get the numpy object cdef double *w_p # get the pointers w_p=<double *>w.data
#-------------------------------
Is there a way to do this?
The next works for any numerical package that supports the array protocol:
data_address = int(w.__array_data__[0], 16) w_p = <double *>PyInt_AsLong(data_address)
and declare PyInt_AsLong as:
cdef extern from "Python.h": long PyInt_AsLong(object)
It is important to note that the above solution does not require to compile against the numpy (or any other numerical package) headers at all. See "A Pyrex Agnostic Class" recipe in the SciPy cookbook (http://www.scipy.org/Cookbook) for a more complete example.
Regards,
participants (3)
-
Brian Blais
-
Francesc Altet
-
Robert Kern