Pierre de Buyl's homepage

Compiling a Fortran library for Python

The ability to call Fortran code from Python has been and still is essential to several scientific packages, including the widely used SciPy library. One widely used tool to make the Fortran code accessible to Python is the f2py library that is bundled with NumPy.

Here, I review how one can write portable and easy to compile Fortran routines.

Solution

f2py is a really powerful tool and its features include the ability to pass Python-defined callbacks to Fortran routines. I have found however that configuring a proper build chain with f2py is a bit annoying. Well, building Fortran sources from a setup.py file is not that easy.

An alternative is to use the "recent" (i.e. 2003) interoperability features of Fortran and provide your code as a library. In short, here's why you could want to use them:

  • Definition of common types that is accessible from Fortran: a real(c_double) in Fortran is a double in C, an integer(c_int) is an int in C, etc.
  • It is possible to declare a subroutine with the bind(c) so that the calling convention and the routine name is well defined. It is possible to customize the name with bind(c, name='public_function').
  • It is possible use "pass by value" arguments with the value attribute.
  • The library is compiled without using distutils.

A consequent drawback of this approach is that there is no automated binding generator. Following the suggestion on fortran90.org, I wrote manually a Fortran wrapper that has uses bind(c) and interoperable datatypes and then a Cython wrapper that would make it available to Python. I made this choice so that the initial Fortran file is completely unmodified and so remains "binding agnostic".

There is a Fortran module, a Fortran wrapper, and a Cython wrapper. The end result will be a Fortran shared library (here, libbrownian.so) and a Python module brownian_wrapper.so.

The immense benefit is that compiling this is very easy. The main line to obtain libbrownian.so is gcc -shared -o libbrownian.so *.o -lgfortran. Then, the setup.py file is standard. You have to declare the use of the libraries brownian and gfortran (the latter part depends on your compiler, still).

You system might complain about not finding libbrownian.so here, as I did not copy it along. If that is the case, adjust your $LD_LIBRARY_PATH.

Wrap up

There is now an alternative method to access Fortran code from Python and my idea is simply to compile the Fortran part as a library to avoid distutils complexity for dealing with Fortran. This approach requires more work but should be more portable and relies on standard tools: the Fortran interoperability features and Cython.

I tested the code with Intel Fortran too with success.

Comments !

Generated with Pelican. Theme based on MIT-licensed Skeleton.