# Introduction
###### tags: `book`
*Authors:* Kjell Jorner, ...
***
In recent years, Python has taken over as the most commonly used language in applied science.
Although Python itself as a scripting language is quite slow, it often serves as a [glue](https://numpy.org/doc/stable/user/c-info.python-as-glue.html) between computationally demanding procedures written in compiled languages such as Fortran or C.
Prime examples of this approch are the [NumPy](https://numpy.org) and [SciPy](https://scipy.org) packages that power applications such as machine learning via [scikit-learn](https://scikit-learn.org/stable/) and quantum chemistry via [PySCF](https://pyscf.org).
There are a number of reasons why you would want to interface Python and Fortran, such as:
* Making your Fortran application available within the Python eco-system
* Speeding up slow parts of a Python code
There are two main approaches to accessing Fortran from Python:
* Automatic interface generation
* Writing an explicit C interface in Fortran
Behind the scenes, the automatic interface generators actually create a C interface for you, so the approaches don't really differ that much technically.
But the user experience and ease of use is different.
## Examples
Using your Fortran code in Python really isn't that difficult
Here are two basic examples of the different approaches.
### Automatic interface generation with [f2py](https://numpy.org/doc/stable/f2py/)
We start with a simple Fortran function that adds two numbers:
```fortran
integer function add(a, b)
integer, intent(in) :: a, b
add = a + b
end function add
```
We place this function in a file called `add.f90` and use `f2py` to wrap it into a Python module called `add`
```shell
python -m numpy.f2py -c add.f90 -m add
```
A shared library file is created, in this case on MacOS with Python 3.9 it is called `add.cpython-39-darwin.so`, but the exact name is not important.
This library can be imported directly into Python and we can use the function as a conventional Python function:
```python
>>> from add import add
>>> add(1, 2)
3
```
### C interface with ctypes
#### Adapting the function
We start with the same function from the previous section, but now we need to adapt it to be interoperable with C:
```fortran
module mod_add
use, intrinsic :: iso_c_binding, only: c_int
implicit none
contains
integer(c_int) function add(a, b) bind(c)
integer(c_int), value, intent(in) :: a, b
add = a + b
end function add
end module mod_add
```
First, we needed to wrap the function in a module, `mod_add` that we put in a file named `mod_add.f90`.
Second, we needed to add a number of code elements to ensure C interoperability:
`use, intrinsic :: iso_c_binding, only: c_int`
: This imports the `c_int` integer type from the intrinsic module `iso_c_binding` which provides support for C interoperability.
`integer(c_int)`
: Variable types need to be C interoperable.
`bind(c)`
: Notifies the compiler that the function should be C interoperable.
`value`
: Notifies the compiler that the variable will be passed by value rather than reference.
#### Compiling to a shared library
We now need to compile the function into a shared library, here using `gfortran`:
```shell
gfortran -shared -fPIC mod_add.f90 -o mod_add.so
```
This creates the shared library file `mod_add.so`
#### Importing the shared library from Python
We can now import and use the function in Python with the built-in `ctypes` library:
```python
>>> from ctypes import CDLL
>>> lib = CDLL("mod_add.so")
>>> lib.add(1, 2)
3
```
Actually, we were a bit sloppy in the previous example as we should really match our variable types to conform to those of our Fortran function:
```python
>>> from ctypes import CDLL, c_int
>>> lib = CDLL("mod_add.so")
>>> lib.add(c_int(1), c_int(2))
3
```
## Pros and cons with the two approaches
At this point you might be thinking that the explicit C interface seems awfully complicated compared to automatic interface generation with `f2py`.
Indeed, `f2py` is very convenient when wrapping individual functions or subroutines, but currently has some important limitations such as lack of support for derived types.
Additionally, when writing more elaborate APIs, the explicit C approach is much more flexible and often preferable.
It also gives you a bonus C interface that could be used from other programming languages than Python.