# Rationale

Fantastic as Python is, it has its own drawbacks, and one of the largest drawbacks is execution speed. Pure Python is quite slow, and this is why one should use `numpy` whenever possible, because it runs C/Fortran code under the hood.

In case some algorithms are not provided by `numpy`, `scipy` or some well established packages, one can implement the algorithm in Fortran or C, and use a tool called f2py to convert the Fortran/C code into a Python module.

# General f2py usage

Wrapping Frotran/C to python using f2py consists of the following steps:

1. create the signature file, containing descriptions of the function/subroutine. In case of Fortran, f2py can create the initial signature file by scanning the Fortran source code and catching all relevant info needed to create wrapper functions.
2. Optional: edit the signature file to optimize wrappers.
3. Read the signature file and write a Python C API module containing Fortran/C/Python bindings.
4. Compile all sources and builds an extension module containing the wrappers.

Depending on a particular situation, these steps can be carried out in one command or step-by-step.

Below is a sample Fortran 77 program for illustration:

``````C FILE: FIB1.F
SUBROUTINE FIB(A,N)
C
C     CALCULATE FIRST N FIBONACCI NUMBERS
C
INTEGER N
REAL*8 A(N)
DO I=1,N
IF (I.EQ.1) THEN
A(I) = 0.0D0
ELSEIF (I.EQ.2) THEN
A(I) = 1.0D0
ELSE
A(I) = A(I-1) + A(I-2)
ENDIF
ENDDO
END
C END FILE FIB1.F
``````

## The quick way

To wrap the Fortran subroutine `FIB` to python, run

``````f2py -c fib1.f -m fib1
``````

This builds an extension module (`fib1.so`) in the current directory. To access the module in Python, use

``````import fib1
print fib1.fib.__doc__
``````

NOTE that `f2py` implements basic compatibility checks between related arguments in order to avoid any unexpected crashes.

When a `numpy` array, that is Fortran contiguous and has a `dtype` corresponding to presumed Fortran type, is used as an input array argument, then its C pointer is directly passed to Fortran.

Otherwise, f2py makes a contiguous copy (with a proper dtype) of the input array and passes C pointer of the copy to Fortran subroutine.

## The smart way

### 1. Create signature file from `fib1.f`

``````f2py fib1.f -m fib2 -h fib2.pyf
``````

This saves the signature file (`-h` flag) to `fib2.pyf`. Its content is shown below:

``````!    -*- f90 -*-
python module fib2 ! in
interface  ! in :fib2
subroutine fib(a,n) ! in :fib2:fib1.f
real*8 dimension(n) :: a
integer optional,check(len(a)>=n),depend(a) :: n=len(a)
end subroutine fib
end interface
end python module fib2

! This file was auto-generated with f2py (version:2.28.198-1366).
! See http://cens.ioc.ee/projects/f2py2e/
``````

### 2. Edit the signature file

We will teach f2py that the argument `n` is an input argument (use `intent(in)` attribute) and that the result, i.e. the contents of `a` after calling Fortran function `FIB`, should be returned to Python (use `intent(out)` attribute).

In addition, an array `a` should be created dynamically using the size given by he input argument `n` (use `depend(n)` attribute) to indicate dependence relation.

The content of a modified version of `fib1.pyf` (saved as `fib2.pyf`) is as follows:

``````!    -*- f90 -*-
python module fib2
interface
subroutine fib(a,n)
real*8 dimension(n),intent(out),depend(n) :: a
integer intent(in) :: n
end subroutine fib
end interface
end python module fib2
``````

### 3. Build the extension module

``````f2py -c fib2.pyf fib2.f
``````

### 4. Use in Python

``````import fib2
print(fib2.fib(8))
``````

## Scenario

Need to create a wrapper for a fortran module (e.g. `mod1.f90`), which calls subprogams in another source file (e.g. `mod2.f90`).

### Solution

1. Compile each module first:

``````gfortran -c mod2.f90
gfortran -c mod1.f90
``````

NOTE that `mod2.f90` goes first as it is called in `mod1.f90`.

2. Then create the wrapper signature:

``````f2py mod1.f90 -m mod1 -h mod1.pyf
``````

Edit `mod1.pyf` if needed.

3. Then compile:

``````f2py -c mo1.pyf mod2.f90 mod1.f90
``````

NOTE here the order of `mod1.f90` and `mod2.f90` doesn’t seem to matter.

## scenario 1

Need to create a wrapper using `f2py` for a fortran module (e.g. `module.f90`), which calls a method (e.g. `dbdsqr`) in a library (e.g. `LAPACK`).

### solution

No need to wrap the entire `LAPACK` library, only the routines you want. These routines are connected with fortran calls under the hood.

But it requires you to provide the path to link to the library.

E.g.

``````f2py -L/path/to/lapack -llapack -m module -c module.f
``````

## scenario 2

Need to create a wrapper using `fftw3` for a fortran module (e.g. `fftconv2d.f90`), which includes `fftw3` by `include "fftw3.f"`.

The compilation method:

``````f2py -c -L/usr/lib -lfftw3 -I/usr/include -m fftconv2d fftconv2d.f90
``````

# A pitfall regarding precision control

In defining precision levels in modules in the following manner:

``````module mod
implicit none

integer, parameter :: ikind = selected_real_kind(15)
public sub

contains
subroutine sub(x,...)
implicit none
...
real(kind=ikind), dimension(:) :: x
...
``````

This works in Fortran, but doesn’t work well with `f2py`: after passing in the data, the values would go nuts. The solution is not to define `ikind` outside subroutines, instead, put it inside:

``````module mod
implicit none

public sub

contains
subroutine sub(x,...)
implicit none
integer, parameter :: ikind = selected_real_kind(15)
real(kind=ikind), dimension(:) :: x
...
``````

Also note that the following "nested" definition doesn’t work either:

``````module mod
implicit none

integer, parameter :: ikind0 = 15
public sub

contains
subroutine sub(x,...)
implicit none
integer, parameter :: ikind = selected_real_kind(ikind0)
real(kind=ikind), dimension(:) :: x
...
``````

### One comment

1. […] Lastly, one can use f2py to compile the Fortran code into a Python module. For more information regarding this process, check out this post Use f2py to compile Python module. […]