[Numpy-discussion] Problem accessing elements of an array of dtype="O" from C

C. Ball ceball at users.sourceforge.net
Fri Feb 8 07:56:53 EST 2008


Travis E. Oliphant <oliphant <at> enthought.com> writes:
[...]
> The problem here is that iter->dataptr should be re-cast to a PyObject 
> ** because what is contained at the memory location is a *pointer* to 
> the PyObject.   Thus, you have to de-reference iter->dataptr to get the 
> PyObject * that you want:

Thanks for pointing out that mistake, Travis. You were correct, and
the code now works - great!

...Well, it works when called from Instant, but we still have a
problem using it with Weave. As I've mentioned before, we tried to
adapt Weave to work with arrays of dtype="O", but something is still
not working.

The small pieces of C below show code that works when called from
Instant, and almost identical C code that does not work when called
from Weave. Presumably, Weave still has a problem with converting
arrays of dtype="O".


------------------------------------------------------------

Working C code (used with Instant; as posted before, but with Travis's
correction):

"""
void loop(PyObject* a_){

 PyArrayIterObject *iter;
 iter = (PyArrayIterObject *)PyArray_IterNew(a_);

 while (iter->index < iter->size) {
     PyObject **cf = (PyObject **)(iter->dataptr);
     PyObject *num_obj = PyObject_GetAttrString(*cf,"num");

     double num_ = PyFloat_AsDouble(num_obj);
     printf("%f\\n",num_);

     PyArray_ITER_NEXT(iter);
 }
return;
}
"""

C code used with Weave (Weave patched as given in
http://article.gmane.org/gmane.comp.python.scientific.devel/7264):

code="""
   // get "cannot convert 'py::object*' to 'PyObject*' 
   // in argument passing" without this...
   PyObject *a_ = (PyObject *)a;

   PyArrayIterObject *iter;
   iter = (PyArrayIterObject *)PyArray_IterNew(a_);

   while (iter->index < iter->size) {
       PyObject **cf = (PyObject **)(iter->dataptr);
       PyObject *num_obj = PyObject_GetAttrString(*cf,"num");

       double num_ = PyFloat_AsDouble(num_obj);
       printf("%f\\n",num_);

       PyArray_ITER_NEXT(iter);
   }
"""
weave.inline(code,['a'],local_dict=locals(),verbose=1)


Python array of objects:

class CF(object):
    def __init__(self,num=0.0):
        self.num = num

objs = numpy.array([[CF(0.0),CF(0.1),CF(0.2)],
  		    [CF(1.0),CF(1.1),CF(1.2)]],dtype=object)


# Pass objs to the two functions above. The first version, used with
# Instant, works fine. The second version, used with Weave, causes
# a segmentation fault.

------------------------------------------------------------



We already have a lot of code written for Weave, and it seems to allow
simpler inlining of C code than does Instant (though I might be wrong),
so we'd really like to be able to continue to use Weave.

I'll file a bug report for Weave, but I wanted to point out the problem 
on the numpy list in case anyone here has an idea (since Weave was part
of numpy for a long time).


Thanks for your help,
Chris





More information about the NumPy-Discussion mailing list