Re: [f2py] Puzzling difference in building wrapper function

Pearu Peterson <[email protected]> Mon, 06 Dec 2010 09:52:23 +0200
Newsgroups gmane.comp.python.f2py.user
Message-ID <[email protected]>
Hi Mark,
The bug is now fixed in numpy git repository.
Thanks for the bug report!
Pearu

On 12/01/2010 09:25 PM, Mark Oberfield wrote:
> Hi Pearu&  Everyone,
>
> I've gotten different results with my module depending on how I build
> it using f2py.  Here's simple code and steps that reproduce the
> puzzle:
>
> --- begin a.f ---
>        SUBROUTINE A
>
> Cf2py intent(callback) RUN_PYTHON
> Cf2py CHARACTER*4 str
> Cf2py CHARACTER*(*) r
> Cf2py DIMENSION fdata(n1,n2)
> Cf2py INTEGER n1,n2,n3
> Cf2py intent(inout) r,n3
>
>        EXTERNAL RUN_PYTHON
>
> Cf2py CALL RUN_PYTHON(str,fdata,f1,r,n3,n1,n2)
>
>        PRINT *, 'ENTERED A'
>        CALL B
>        PRINT *, 'LEAVING A'
>        RETURN
>        END
> --- end a.f ---
>
> --- begin bc.f ---
>        SUBROUTINE B
>
>        PARAMETER(N1=2)
>        PARAMETER(N2=2)
>        CHARACTER*4 STR
>        DIMENSION FDATA(N1,N2)
>
>        STR='KAAA'
>        DATA FDATA /1,2,4,8/
>
>        PRINT *,'ENTERED B'
>        CALL C(STR,FDATA,N1,N2)
>        PRINT *,'LEAVING B'
>
>        RETURN
>        END
>
>        SUBROUTINE C(STR,FDATA,N1,N2)
>
>        PARAMETER(ISTRLEN=10)
>
>        CHARACTER*4 STR
>        CHARACTER*(ISTRLEN) R
>
>        INTEGER IRESLEN,N1,N2,N3
>        DIMENSION FDATA(N1,N2)
>        EXTERNAL RUN_PYTHON
>
>        F1=9999.
>        R=' '
>        IRESLEN=ISTRLEN
>
>        PRINT *,'ENTERED C'
>        CALL RUN_PYTHON(STR,FDATA,F1,R,IRESLEN,N1,N2)
>        PRINT *, R(1:IRESLEN)
>        PRINT *,'LEAVING C'
>
>        RETURN
>        END
> --- end bc.f ---
>
> If I build it straightforwardly,
>
> f2py --quiet -c -m simple --f77flags=-qextname=a a.f bc.o
>
> this produces a python module 'simple'
>
> If I produce a signature file first, then a module 'puzzled',
>
> f2py --quiet -m puzzled -h puzzled.pyf a.f
>
> --- begin puzzled.pyf ---
> !    -*- f90 -*-
> ! Note: the context of this file is case sensitive.
>
> python module a__user__routines
>      interface a_user_interface
>          subroutine run_python(str,fdata,f1,r,n3,n1,n2) ! in :puzzled:a.f:a:unknown_interface
>              intent(callback) run_python
>              character*4 :: str
>              real dimension(n1,n2) :: fdata
>              real :: f1
>              character*(*) intent(inout) :: r
>              integer intent(inout) :: n3
>              integer optional,check(shape(fdata,0)==n1),depend(fdata) :: n1=shape(fdata,0)
>              integer optional,check(shape(fdata,1)==n2),depend(fdata) :: n2=shape(fdata,1)
>          end subroutine run_python
>      end interface a_user_interface
> end python module a__user__routines
> python module puzzled ! in
>      interface  ! in :puzzled
>          subroutine a ! in :puzzled:a.f
>              use a__user__routines
>              intent(callback) run_python
>              external run_python
>          end subroutine a
>      end interface
> end python module puzzled
>
> ! This file was auto-generated with f2py (version:1).
> ! See http://cens.ioc.ee/projects/f2py2e/
> --- end of puzzled.pyf ---
>
> f2py --quiet -c -m puzzled puzzled.pyf a.f bc.o
>
> Now I look at the results:
>
>>>> import simple
>>>> print simple.a.__doc__
> a - Function signature:
>    a(run_python,[run_python_extra_args])
> Required arguments:
>    run_python : call-back function
> Optional arguments:
>    run_python_extra_args := () input tuple
> Call-back functions:
>    def run_python(str,fdata,f1,r,n3,[n1,n2]): return
>    Required arguments:
>      str : input string(len=4)
>      fdata : input rank-2 array('f') with bounds (n1,n2)
>      f1 : input float
>      r : in/output rank-0 array(string(len=-1),'c')
>      n3 : in/output rank-0 array(int,'i')
>    Optional arguments:
>      n1 := shape(fdata,0) input int
>      n2 := shape(fdata,1) input int
>
>>>> import puzzled
>>>> print puzzled.a.__doc__
> a - Function signature:
>    a(run_python,[run_python_extra_args])
> Required arguments:
>    run_python : call-back function
> Optional arguments:
>    run_python_extra_args := () input tuple
> Call-back functions:
>    def run_python(str,fdata,f1,r,n3,run_python,[n1,n2]): return
>    Required arguments:
>      str : input string(len=4)
>      fdata : input rank-2 array('f') with bounds (n1,n2)
>      f1 : input float
>      r : in/output rank-0 array(string(len=-1),'c')
>      n3 : in/output rank-0 array(int,'i')
>      run_python : input float
>    Optional arguments:
>      n1 := shape(fdata,0) input int
>      n2 := shape(fdata,1) input int
>
> Why is there a bogus 'run_python' argument to the function
> 'run_python'?
>
> simple.so:  def run_python(str,fdata,f1,r,n3,[n1,n2]): return
> puzzled.so: def run_python(str,fdata,f1,r,n3,run_python,[n1,n2]): return
>
> Where did it come from?  How to keep f2py from putting this entry
> in there?
>
> Mark