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

Egor Zindy ezindy@gmail....
Tue Jan 6 08:47:38 CST 2009


Hello again,

I really don't know what came over me when I changed your function
prototype, that wasn't a very thoughtful thing to do!

Maybe I should look into using an 'insertion block' of code in the
> interface file, instead of trying to typemap the array?
>

Insertion blocks... is that %inline code? In which case, yes! Have a look, I
attached a new version that uses some %inline directives in the
dftmagnitude.i file.

Basically, you can inline a new function with an easier prototype to wrap.
The function allocates memory and calls your sms_spectrumMag() function.

my inline function: void my_spectrumMag( int sizeInMag, float *pInRect, int
*sizeOutMag, float **pOutMag)

there's also a %rename directive: %rename (spectrumMag) my_spectrumMag;

I had a go at defining some exceptions too (no memory and odd number of
indexes), but I'm not sure errno is the easiest way to go about it...

Hope this helps!

... and the python test output:

~>python test_dftmagnitude.py
array: [1, 1, 2, 2]
result: [ 1.41421354  2.82842708]

array: [1, 1, 2, 2, 3, 3, 4, 4]
result: [ 1.41421354  2.82842708  4.2426405   5.65685415]

array: [1, 1, 2]
result:
Traceback (most recent call last):
  File "test_dftmagnitude.py", line 15, in <module>
    print "result:",dftmagnitude.spectrumMag(a)
IndexError: Odd number of elements in input array: 3

~>

Regards,
Egor


On Tue, Jan 6, 2009 at 1:06 AM, Rich E <reakinator@gmail.com> wrote:

> Egor,
>
> Thanks for the help.  I think I want to leave the C code as-is
> however, as it is perfectly fine there no knowing 'sizeOutMag' because
> it can deduce both array sizes from one variable.  There are many
> other similar cases in my code (many where the size of the array is
> known by a member of a structure passed to the function).
>
> Maybe I should look into using an 'insertion block' of code in the
> interface file, instead of trying to typemap the array?  I am thinking
> I may just be able to copy the generated code (from SWIG) into my
> interface file to do this, but I have not tried it yet.
>
> I will experiment a little and post again.  Thanks and happy holidays!
>
> regards,
> Rich
>
> On Mon, Jan 5, 2009 at 10:42 AM, Egor Zindy <ezindy@gmail.com> wrote:
> > 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@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@scipy.org
> >> http://projects.scipy.org/mailman/listinfo/numpy-discussion
> >
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://projects.scipy.org/pipermail/numpy-discussion/attachments/20090106/1208a4a1/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dftmagnitude2.zip
Type: application/zip
Size: 10880 bytes
Desc: not available
Url : http://projects.scipy.org/pipermail/numpy-discussion/attachments/20090106/1208a4a1/attachment-0001.zip 


More information about the Numpy-discussion mailing list