Trouble Passing Array of Strings (using Numeric) to C Extension Module


G

goetzie

I am using Python 2.4.1 and Numeric 23.8 and running on Windows XP. I
am passing a Numeric array of strings (objects) to a C Extension module
using the following python code:

import Numeric
import TestDLL # my C Extension Module

a = Numeric.array(['foo', 'bar'], 'O' )
print 'a =', a
print 'type a[0] =', type(a[0])

print TestDLL.StringArrayIn( a )

And here is the relevent code from my C Extension module:

static PyObject * _StringArrayIn( PyObject *self, PyObject *args )
{
PyObject *pObject; // input array
PyArrayObject *pArray; // contiguous array
int iCount;
int iStride;
BOOL bString;

if ( !PyArg_ParseTuple( args, "O", &pObject ) ) return NULL;

if ( ( pArray = ( PyArrayObject * )PyArray_ContiguousFromObject(
pObject, PyArray_OBJECT, 1, 1 ) ) == NULL ) return NULL;

iCount = pArray->dimensions[0];
iStride = pArray->strides[0];

bString = PyString_Check( ( PyObject * )( pArray->data ) );

Py_DECREF( pArray );
return Py_BuildValue( "iiO", iCount, iStride, PyBool_FromLong(
bString ) );
}

static PyMethodDef Methods[] =
{
{ "StringArrayIn", _StringArrayIn, METH_VARARGS, "" },
{ NULL, NULL, 0, NULL } /*
Sentinel */
};

This code produces the following output:

a = [foo bar ]
type a[0] = <type 'str'>
(2, 4, False)

The iCount and iStride values are as I expect (2 and 4 respectively),
but performing a PyString_Check on the first array element (or more
likely, what I think is the first array element) returns 'False'.

BTW, the output above is from running the Python interpreter from the
command line. When I run this code in IDLE, I get a GPF if I don't
comment out the call to the PyString_Check function :-(

What am I doing wrong here?
 
Ad

Advertisements

T

Travis E. Oliphant

goetzie said:
I am using Python 2.4.1 and Numeric 23.8 and running on Windows XP. I
am passing a Numeric array of strings (objects) to a C Extension module
using the following python code:

Numeric 23.8 is *very* old and unsupported. Unless you absolutely have
to use Numeric (then use 24.2), NumPy is a better choice for new code.

With that advice aside. Let's see...
And here is the relevent code from my C Extension module:

static PyObject * _StringArrayIn( PyObject *self, PyObject *args )
{
PyObject *pObject; // input array
PyArrayObject *pArray; // contiguous array
int iCount;
int iStride;
BOOL bString;

if ( !PyArg_ParseTuple( args, "O", &pObject ) ) return NULL;

if ( ( pArray = ( PyArrayObject * )PyArray_ContiguousFromObject(
pObject, PyArray_OBJECT, 1, 1 ) ) == NULL ) return NULL;

iCount = pArray->dimensions[0];
iStride = pArray->strides[0];

bString = PyString_Check( ( PyObject * )( pArray->data ) );

This is the problem.:

pArray->data should be interpreted as (PyObject **) -- an array of
PyObject *'s, and then de-referenced to get the PyObject * present at
the first address

So. this should work to check that the first entry in the array is a
string:

PyString_Check( *( ( PyObject ** )( pArray->data ) ) );


By the way, NumPy has support for true string (and unicode) arrays (as
well as object arrays like this)...

-Travis
 
Ad

Advertisements

G

goetzie

Travis said:
PyString_Check( *( ( PyObject ** )( pArray->data ) ) );

Thank you very much Travis! My mistake is now quite obvious (and
should have been right from the start).

Regarding NumPy, I probably should upgrade from Numeric. It's just
hard to change something that is currently working fine for me and my
users.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top