NumPy (numarray) problem with C code

David M. Cooke cookedm+news at physics.mcmaster.ca
Wed Mar 10 14:48:22 EST 2004


At some point, Marc Schellens <m_schellens at hotmail.com> wrote:

> Following the NumPy documentation, I took over some C code,
> but run into an error.
> Does anybody have a suggestion?
> Thanks,
> marc
>
>
> gdlpython.cpp:225: `PyArray_Type' undeclared (first use this function)
>
> #include <python2.3/Python.h>
> // python numarray is used
> #include <python2.3/numarray/arrayobject.h>

I don't know how you're compiling, but you're probably better off
using
#include "Python.h"
#include "numarray/arrayobject.h"

and specifying the proper include directory. This way you're not
hardcoded to the Python version. distutils automatically adds the
proper directory to the compile line, for instance.

You're using numarray, so you may want to use the numarray interface
instead of the Numeric compability interface. Include
"numarray/libnumarray.h" instead of "numarray/arrayobject.h"

> // ...
>
> BaseGDL* FromPython( PyObject* pyObj)
> {
>    PyObject *object;
>
> // following is line 225
>    if( !PyArg_ParseTuple(pyObj, "O!", &PyArray_Type, &object))

There is no such thing as PyArray_Type in numarray, and actually,
there isn't one array type. I'd check for the specific
string/long/complex/double types first (your code below)..

>      {
>        // non-array - try other
>        PyErr_Clear();
>        // string
>        char* s;
>        if( PyArg_ParseTuple(pyObj, "s", s))
> 	return new DStringGDL( string(s));
>        PyErr_Clear();
>        // integer
>        DLong l;
>        if( PyArg_ParseTuple(pyObj, "l", &l))
> 	return new DLongGDL( l);
>        PyErr_Clear();
>        // complex
>        Py_complex c;
>        if( PyArg_ParseTuple(pyObj, "D", &c))
> 	{
> 	  DComplexDbl cc( c.real, c.imag);
> 	  return new DComplexDblGDL( cc);
> 	}
>        PyErr_Clear();
>        // float
>        DDouble d;
>        if( PyArg_ParseTuple(pyObj, "d", &d))
> 	return new DDoubleGDL( d);
>
>        throw GDLException( "FromPython: Cannot convert python object.") ;
>      }

and use NA_InputArray() to get the array. This returns NULL if it
can't make the argument an array. You're using the Numeric
compatibility functions below; you might as well use the numarray
equivalents instead.

>    // array type
>    PyArrayObject* array = (PyArrayObject*) object;
>
>    int nDim = array->nd;
>    int item_type = array->descr->type_num;
>
>    // make array contiguous
> //   array = static_cast< PyArrayObject*>
> //     (PyArray_ContiguousFromObject( object,
> // 				   item_type,
> // 				   0,0));
>    array = (PyArrayObject*) PyArray_ContiguousFromObject( object,
> 							 item_type,
> 							 0,0);
>    if( array == NULL)
>      throw GDLException( "FromPython: Error making array contiguous.") ;

Note that array will be NULL also if it's not an array; this would be
a better way to use it.

Replace the above with something like

PyArrayObject* array = NA_InputArray(object, tAny, NUM_C_ARRAY);
if (array == NULLL) {
   throw GDLException( "FromPython: Error making array contiguous.") ;
}
int item_type = array->descr->type_num;

Double-check the numarray C API documentation as to whether you should use
NA_InputArray or NA_IoArray.

Haven't looked at the following carefully:
>    size_t dimArr[ MAXRANK];
>    if( nDim > MAXRANK)
>      {
>      Warning( "FromPython: Array has more than "+MAXRANK_STR+
> 	     " dimensions. Extending last one.");
>      size_t lastDim = array->dimensions[ MAXRANK-1];
>      for( size_t i=MAXRANK; i<nDim; ++i) lastDim *= array->dimensions[ i];
>      for( size_t i=0; i<MAXRANK-1; ++i)
>        dimArr[ i] = array->dimensions[ i];
>      dimArr[ MAXRANK-1] = lastDim;
>      nDim = MAXRANK;
>      }
>    else
>      {
>        for( size_t i=0; i<nDim; ++i)
> 	dimArr[ i] = array->dimensions[ i];
>      }
>
>    dimension dim( dimArr, nDim);


Use the numarray types instead: tUInt8, tInt8, tInt16, tFloat64, etc:

>    switch( item_type)
>      {
>        // case PyArray_NOTYPE:  //UNDEF***
>      case PyArray_UBYTE:   //BYTE
>        return NewFromPyArrayObject< DByteGDL>( dim, array);
>      case PyArray_SHORT:   //INT
>        return NewFromPyArrayObject< DIntGDL>( dim, array);
>      case PyArray_INT:     //LONG	
>        return NewFromPyArrayObject< DLongGDL>( dim, array);
>      case PyArray_FLOAT:   //FLOAT	
>        return NewFromPyArrayObject< DFloatGDL>( dim, array);
>      case PyArray_DOUBLE:  //DOUBLE	
>        return NewFromPyArrayObject< DDoubleGDL>( dim, array);
>      case PyArray_CFLOAT:  //COMPLEX	
>        return NewFromPyArrayObject< DComplexGDL>( dim, array);
>        // case PyArray_NOTYPE:  //STRING***	
>        // case PyArray_NOTYPE:  //STRUCT***	
>      case PyArray_CDOUBLE: //COMPLEXDBL	
>        return NewFromPyArrayObject< DComplexDblGDL>( dim, array);
>        // case PyArray_NOTYPE:  //PTR***		
>        // case PyArray_NOTYPE:  //OBJECT***
>      case tUInt16:         //UINT*
>        return NewFromPyArrayObject< DUIntGDL>( dim, array);
>      case tUInt32:         //ULONG*
>        return NewFromPyArrayObject< DULongGDL>( dim, array);
>      default:
>        throw GDLException( "FromPython: Unknown array type.") ;
>      }
>
>    return NULL; // compiler shut-up
> }

-- 
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca



More information about the Python-list mailing list