# 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.