[f2py] Puzzling difference in building wrapper function

Mark Oberfield Mark.Oberfield at noaa.gov
Wed Dec 1 21:25:19 EET 2010


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
-- 
"Man does not live by words alone, despite the fact that sometimes he
has to eat them."
	-- Adlai Stevenson



More information about the f2py-users mailing list