
Title:     Wrapping F compiled Fortran 90 modules with F2PY
           ================================================

Rationale: The F compiler does not support external procedures which
           makes it impossible to use it in F2PY in a normal way.
           This document describes a workaround to this problem so
           that F compiled codes can be still wrapped with F2PY.

Author:    Pearu Peterson
Date:      May 8, 2002

Acknowledgement: Thanks to Siegfried Gonzi who hammered me to produce
           this document.

Normally wrapping Fortran 90 modules to Python using F2PY is carried
out with the following command

  f2py -c -m fun foo.f90

where file foo.f90 contains, for example,

module foo
  public :: bar
  contains
  subroutine bar (a)
    integer,intent(inout) ::  a
    print *,"Hello from foo.bar"
    print *,"a=",a
    a = a + 5
    print *,"a=",a
  end subroutine bar
end module foo

Then with a supported F90 compiler (running `f2py -c --help-compiler'
will display the found compilers) f2py will generate an extension
module fun.so into the current directory and the Fortran module foo
subroutine bar can be called from Python as follows

>>> import fun
>>> print fun.foo.bar.__doc__
bar - Function signature:
  bar(a)
Required arguments:
  a : in/output rank-0 array(int,'i')

>>> from Numeric import array
>>> a = array(3)
>>> fun.foo.bar(a)
 Hello from foo.bar
 a=           3
 a=           8
>>> a
8
>>>

This works nicely with all supported Fortran compilers.

However, the F compiler (http://www.fortran.com/F/compilers.html) is
an exception. Namely, the F compiler is designed to recognize only
module procedures (and main programs, of course) but F2PY needs to
compile also the so-called external procedures that it generates to
facilitate accessing Fortran F90 module procedures from C and
subsequently from Python.  As a result, wrapping F compiled Fortran
procedures to Python is _not_ possible using the simple procedure as
described above. But, there is a workaround that I'll describe below
in five steps.

1) Compile foo.f90:

   F -c foo.f90

This creates an object file foo.o into the current directory.

2) Create the signature file:

  f2py foo.f90 -h foo.pyf

This creates a file foo.pyf containing

module foo ! in foo.f90
    real public :: bar
    subroutine bar(a) ! in foo.f90:foo
        integer intent(inout) :: a
    end subroutine bar
end module foo

3) Open the file foo.pyf with your favorite text editor and change the
   above signature to

python module foo
  interface
    subroutine bar(a)
        fortranname foo_MP_bar
        intent(c) bar
        integer intent(in,out) :: a
    end subroutine bar
  end interface
end python module foo

The most important modifications are

 a) adding `python' keyword everywhere before the `module' keyword

 b) including an `interface' block around the all subroutine blocks.

 c) specifying the real symbol name of the subroutine using
    `fortranname' statement. F generated symbol names are in the form
    <module name>_MP_<subroutine name>

 d) specifying that subroutine is `intent(c)'.

Notice that the `intent(inout)' attribute is changed to
`intent(in,out)' that instructs the wrapper to return the modified
value of `a'.

4) Build the extension module

   f2py -c foo.pyf foo.o --fcompiler=Gnu /opt/F/lib/quickfit.o \
       /opt/F/lib/libf96.a

This will create the extension module foo.so into the current
directory.  Notice that you must use Gnu compiler (gcc) for linking.
And the paths to F specific object files and libraries may differ for
your F installation.

5) Finally, we can call the module subroutine `bar' from Python

>>> import foo
>>> print foo.bar.__doc__
bar - Function signature:
  a = bar(a)
Required arguments:
  a : input int
Return objects:
  a : int

>>> foo.bar(3)
8
>>>

Notice that the F compiled module procedures are called as ordinary
external procedures. Also I/O seems to be lacking for F compiled
Fortran modules.

Enjoy,
	Pearu
