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

Egor Zindy ezindy at gmail.com
Mon Jan 5 04:42:31 EST 2009


Hello Rich,

sorry it took so long to answer back, holidays and all :-)

That's exactly the kind of SWIG / numpy.i problems I've been working on over
the past few months: How to generate an array you don't know the size of
a-priori, and then handle the memory deallocation seamlessly. In your case,
you know that the output array will be half the size of the input array, but
this falls under the more general case of "not knowing the output size
a-priori".

Have a look at the files attached. I've rewritten your function header as:
void sms_spectrumMag( int sizeInMag, float *pInRect, int *sizeOutMag, float
**pOutMag);

Easy to see what the input and output arrays are now. Then my numpy.i
handles the memory deallocation of the **pOutMag array.

I've actually moved my numpy.i explanations to the scipy/numpy cookbook last
week :-)
http://www.scipy.org/Cookbook/SWIG_Memory_Deallocation

Hope it all makes sense. If you have any questions, don't hesitate!

>python test_dftmagnitude.py
[1, 1, 2, 2]
[ 1.41421354  2.82842708]
[1, 1, 2, 2, 3, 3, 4, 4]
[ 1.41421354  2.82842708  4.2426405   5.65685415]
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
[ 1.41421354  2.82842708  4.2426405   5.65685415  7.07106781]

Regards,
Egor

On Wed, Dec 24, 2008 at 1:52 AM, Rich E <reakinator at gmail.com> wrote:

> 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
> _______________________________________________
> Numpy-discussion mailing list
> Numpy-discussion at scipy.org
> http://projects.scipy.org/mailman/listinfo/numpy-discussion
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20090105/a5964e50/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dftmagnitude.zip
Type: application/zip
Size: 10857 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20090105/a5964e50/attachment.zip>


More information about the NumPy-Discussion mailing list