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

Rich E reakinator@gmail....
Mon Jan 5 10:06:06 CST 2009


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
>
>


More information about the Numpy-discussion mailing list