bundles / numpy 2.4.4 / docs
Doc
Three ways to wrap - getting started
docs/f2py:f2py.getting-started
Wrapping Fortran or C functions to Python using F2PY consists of the following steps:
Creating the so-called signature file that contains descriptions of wrappers to Fortran or C functions, also called the signatures of the functions. For Fortran routines, F2PY can create an initial signature file by scanning Fortran source codes and tracking all relevant information needed to create wrapper functions.
Optionally, F2PY-created signature files can be edited to optimize wrapper functions, which can make them "smarter" and more "Pythonic".
F2PY reads a signature file and writes a Python C/API module containing Fortran/C/Python bindings.
F2PY compiles all sources and builds an extension module containing the wrappers.
In building the extension modules, F2PY uses
mesonand used to usenumpy.distutilsFor different build systems, see f2py-bldsys.
Depending on your operating system, you may need to install the Python development headers (which provide the file
Python.h) separately. In Linux Debian-based distributions this package should be calledpython3-dev, in Fedora-based distributions it ispython3-devel. For macOS, depending how Python was installed, your mileage may vary. In Windows, the headers are typically installed already, see f2py-windows.
Depending on the situation, these steps can be carried out in a single composite command or step-by-step; in which case some steps can be omitted or combined with others.
Below, we describe three typical approaches of using F2PY with Fortran 77. These can be read in order of increasing effort, but also cater to different access levels depending on whether the Fortran code can be freely modified.
The following example Fortran 77 code will be used for illustration, save it as fib1.f:
The quick way
The quickest way to wrap the Fortran subroutine FIB for use in Python is to run
python -m numpy.f2py -c fib1.f -m fib1or, alternatively, if the f2py command-line tool is available,
f2py -c fib1.f -m fib1This command compiles and wraps fib1.f (-c) to create the extension module fib1.so (-m) in the current directory. A list of command line options can be seen by executing python -m numpy.f2py. Now, in Python the Fortran subroutine FIB is accessible via fib1.fib
>>> import numpy as np >>> import fib1 >>> print(fib1.fib.__doc__) fib(a,[n]) Wrapper for ``fib``. Parameters ---------- a : input rank-1 array('d') with bounds (n) Other parameters ---------------- n : input int, optional Default: len(a) >>> a = np.zeros(8, 'd') >>> fib1.fib(a) >>> print(a) [ 0. 1. 1. 2. 3. 5. 8. 13.]
The smart way
If we want to have more control over how F2PY will treat the interface to our Fortran code, we can apply the wrapping steps one by one.
First, we create a signature file from
fib1.fby running:python -m numpy.f2py fib1.f -m fib2 -h fib1.pyfThe signature file is saved to
fib1.pyf(see the-hflag) and its contents are shown below.Next, we'll teach F2PY that the argument
nis an input argument (using theintent(in)attribute) and that the result, i.e., the contents ofaafter calling the Fortran functionFIB, should be returned to Python (using theintent(out)attribute). In addition, an arrayashould be created dynamically using the size determined by the input argumentn(using thedepend(n)attribute to indicate this dependence relation).The contents of a suitably modified version of
fib1.pyf(saved asfib2.pyf) are as follows:Finally, we build the extension module with
numpy.distutilsby running:python -m numpy.f2py -c fib2.pyf fib1.f
In Python
>>> import fib2 >>> print(fib2.fib.__doc__) a = fib(n) Wrapper for ``fib``. Parameters ---------- n : input int Returns ------- a : rank-1 array('d') with bounds (n) >>> print(fib2.fib(8)) [ 0. 1. 1. 2. 3. 5. 8. 13.]
The quick and smart way
The "smart way" of wrapping Fortran functions, as explained above, is suitable for wrapping (e.g. third party) Fortran codes for which modifications to their source codes are not desirable nor even possible.
However, if editing Fortran codes is acceptable, then the generation of an intermediate signature file can be skipped in most cases. F2PY specific attributes can be inserted directly into Fortran source codes using F2PY directives. A F2PY directive consists of special comment lines (starting with Cf2py or !f2py, for example) which are ignored by Fortran compilers but interpreted by F2PY as normal lines.
Consider a modified version of the previous Fortran code with F2PY directives, saved as fib3.f:
Building the extension module can be now carried out in one command
python -m numpy.f2py -c -m fib3 fib3.fNotice that the resulting wrapper to FIB is as "smart" (unambiguous) as in the previous case
>>> import fib3 >>> print(fib3.fib.__doc__) a = fib(n) Wrapper for ``fib``. Parameters ---------- n : input int Returns ------- a : rank-1 array('d') with bounds (n) >>> print(fib3.fib(8)) [ 0. 1. 1. 2. 3. 5. 8. 13.]