[Numpy-discussion] help with typemapping a C function to use numpy arrays

Rich E reakinator@gmail....
Tue Dec 23 10:52:05 CST 2008


Hi list,

My question has to do with the Numpy/SWIG typemapping system.

I recently got the typemaps in numpy.i to work on most of my C
functions that are wrapped using SWIG, if they have arguments of the
form (int sizeArray, float *pArray).

Now I am trying to figure out how to wrap function that aren't of the
form, such as the following function:

/*! \brief compute magnitude spectrum of a DFT
 *
 * \param sizeMag              size of output Magnitude (half of input real FFT)
 * \param pFReal               pointer to input FFT real array
(real/imag floats)
 * \param pFMAg        pointer to float array of magnitude spectrum
 */
void sms_spectrumMag( int sizeMag, float *pInRect, float *pOutMag)
{
       int i, it2;
       float fReal, fImag;

       for (i=0; i<sizeMag; i++)
       {
               it2 = i << 1;
               fReal = pInRect[it2];
               fImag = pInRect[it2+1];
               pOutMag[i] = sqrtf(fReal * fReal + fImag * fImag);
       }
}

There are two arrays, one is half the size of the other.  But, SWIG
doesn't know this, according to the type map it will think *pInRect is
of size sizeMag and will not know anything about *pOutMag.

Ideally in python, I would like to call the function as
sms_spectrumMag(nArray1, nArray2), where nArray1 is twice the size of
nArray2, and nArray2 is of size sizeMag.

I think in order to do this (although if someone has a better
suggestion, I am open to it), I will have to modify the typemap in
order to tell SWIG how to call the C function properly.  I do not want
to have to edit the wrapped C file every time it is regenerated from
the interface file.


Here is a start I made with the existing typemap code in numpy.i (not working):

/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
 */
%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY,
          fragment="NumPy_Macros")
 (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
{
 $1 = is_array($input) && PyArray_EquivTypenums(array_type($input),
                                                DATA_TYPECODE);
}
%typemap(in,
        fragment="NumPy_Fragments")
 (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1)
 (PyArrayObject* array=NULL, int i=0)
{
 array = obj_to_array_no_conversion($input, DATA_TYPECODE);
 if (!array || !require_dimensions(array,1) || !require_contiguous(array)
     || !require_native(array)) SWIG_fail;
 $1 = 1;
 for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i);
 $2 = (DATA_TYPE*) array_data(array);
}

and try to alter it to allow for a conversion of type:
(DIM_TYPE DIM1, DATA_TYPE* ARRAY1, DATA_TYPE* ARRAY2)
where ARRAY1 is size DIM1 * 2 and  ARRAY2 is size DIM1.  Then I can
%apply this to my function that I mentioned in the last post.

So here are my first two questions:

1) where is DIM1 used to declare the array size?  I don't see where it
is used at all, and I need to somewhere multiply it by 2 to declare
the size of ARRAY1

2) I am not understanding where $input comes from, so I do not
understand how to distinguish between ARRAY1 and ARRAY2.  In the
attempt I have already tried, I think I just use the pointer to ARRAY1
twice.

If anyone has suggestions on how to solve this problem, thanks!

regards,
Rich


More information about the Numpy-discussion mailing list