tmp
/
pip-install-ghxuqwgs
/numpy_78e94bf2b6094bf9a1f3d92042f9bf46
/doc
/source
/f2py
/getting-started.rst
====================================== | |
Three ways to wrap - 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 as signatures of the | |
functions. In the case of Fortran routines, F2PY can create initial | |
signature file by scanning Fortran source codes and | |
catching all relevant information needed to create wrapper | |
functions. | |
* Optionally, F2PY created signature files can be edited to optimize | |
wrappers functions, 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 extension modules, F2PY uses | |
``numpy_distutils`` that supports a number of Fortran 77/90/95 | |
compilers, including Gnu, Intel, | |
Sun Fortre, SGI MIPSpro, Absoft, NAG, Compaq etc. compilers. | |
Depending on a particular situation, these steps can be carried out | |
either by just in one command or step-by-step, some steps can be | |
omitted or combined with others. | |
Below I'll describe three typical approaches of using F2PY. | |
The following `example Fortran 77 code`__ will be used for | |
illustration: | |
.. include:: fib1.f | |
:literal: | |
__ fib1.f | |
The quick way | |
============== | |
The quickest way to wrap the Fortran subroutine ``FIB`` to Python is | |
to run | |
:: | |
f2py -c fib1.f -m fib1 | |
This command builds (see ``-c`` flag, execute ``f2py`` without | |
arguments to see the explanation of command line options) an extension | |
module ``fib1.so`` (see ``-m`` flag) to the current directory. Now, in | |
Python the Fortran subroutine ``FIB`` is accessible via ``fib1.fib``:: | |
>>> import numpy | |
>>> import fib1 | |
>>> print fib1.fib.__doc__ | |
fib - Function signature: | |
fib(a,[n]) | |
Required arguments: | |
a : input rank-1 array('d') with bounds (n) | |
Optional arguments: | |
n := len(a) input int | |
>>> a = numpy.zeros(8,'d') | |
>>> fib1.fib(a) | |
>>> print a | |
[ 0. 1. 1. 2. 3. 5. 8. 13.] | |
.. note:: | |
* Note that F2PY found that the second argument ``n`` is the | |
dimension of the first array argument ``a``. Since by default all | |
arguments are input-only arguments, F2PY concludes that ``n`` can | |
be optional with the default value ``len(a)``. | |
* One can use different values for optional ``n``:: | |
>>> a1 = numpy.zeros(8,'d') | |
>>> fib1.fib(a1,6) | |
>>> print a1 | |
[ 0. 1. 1. 2. 3. 5. 0. 0.] | |
but an exception is raised when it is incompatible with the input | |
array ``a``:: | |
>>> fib1.fib(a,10) | |
fib:n=10 | |
Traceback (most recent call last): | |
File "<stdin>", line 1, in ? | |
fib.error: (len(a)>=n) failed for 1st keyword n | |
>>> | |
This demonstrates one of the useful features in F2PY, that it, | |
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. As a result, any possible changes to the (copy of) | |
input array have no effect to the original argument, as | |
demonstrated below:: | |
>>> a = numpy.ones(8,'i') | |
>>> fib1.fib(a) | |
>>> print a | |
[1 1 1 1 1 1 1 1] | |
Clearly, this is not an expected behaviour. The fact that the | |
above example worked with ``dtype=float`` is considered | |
accidental. | |
F2PY provides ``intent(inplace)`` attribute that would modify | |
the attributes of an input array so that any changes made by | |
Fortran routine will be effective also in input argument. For example, | |
if one specifies ``intent(inplace) a`` (see below, how), then | |
the example above would read: | |
>>> a = numpy.ones(8,'i') | |
>>> fib1.fib(a) | |
>>> print a | |
[ 0. 1. 1. 2. 3. 5. 8. 13.] | |
However, the recommended way to get changes made by Fortran | |
subroutine back to python is to use ``intent(out)`` attribute. It | |
is more efficient and a cleaner solution. | |
* The usage of ``fib1.fib`` in Python is very similar to using | |
``FIB`` in Fortran. However, using *in situ* output arguments in | |
Python indicates a poor style as there is no safety mechanism | |
in Python with respect to wrong argument types. When using Fortran | |
or C, compilers naturally discover any type mismatches during | |
compile time but in Python the types must be checked in | |
runtime. So, using *in situ* output arguments in Python may cause | |
difficult to find bugs, not to mention that the codes will be less | |
readable when all required type checks are implemented. | |
Though the demonstrated way of wrapping Fortran routines to Python | |
is very straightforward, it has several drawbacks (see the comments | |
above). These drawbacks are due to the fact that there is no way | |
that F2PY can determine what is the actual intention of one or the | |
other argument, is it input or output argument, or both, or | |
something else. So, F2PY conservatively assumes that all arguments | |
are input arguments by default. | |
However, there are ways (see below) how to "teach" F2PY about the | |
true intentions (among other things) of function arguments; and then | |
F2PY is able to generate more Pythonic (more explicit, easier to | |
use, and less error prone) wrappers to Fortran functions. | |
The smart way | |
============== | |
Let's apply the steps of wrapping Fortran functions to Python one by | |
one. | |
* First, we create a signature file from ``fib1.f`` by running | |
:: | |
f2py fib1.f -m fib2 -h fib1.pyf | |
The signature file is saved to ``fib1.pyf`` (see ``-h`` flag) and | |
its contents is shown below. | |
.. include:: fib1.pyf | |
:literal: | |
* Next, we'll teach F2PY that the argument ``n`` is a 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 | |
the 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: | |
.. include:: fib2.pyf | |
:literal: | |
* And finally, we build the extension module by running | |
:: | |
f2py -c fib2.pyf fib1.f | |
In Python:: | |
>>> import fib2 | |
>>> print fib2.fib.__doc__ | |
fib - Function signature: | |
a = fib(n) | |
Required arguments: | |
n : input int | |
Return objects: | |
a : rank-1 array('d') with bounds (n) | |
>>> print fib2.fib(8) | |
[ 0. 1. 1. 2. 3. 5. 8. 13.] | |
.. note:: | |
* Clearly, the signature of ``fib2.fib`` now corresponds to the | |
intention of Fortran subroutine ``FIB`` more closely: given the | |
number ``n``, ``fib2.fib`` returns the first ``n`` Fibonacci numbers | |
as a Numpy array. Also, the new Python signature ``fib2.fib`` | |
rules out any surprises that we experienced with ``fib1.fib``. | |
* Note that by default using single ``intent(out)`` also implies | |
``intent(hide)``. Argument that has ``intent(hide)`` attribute | |
specified, will not be listed in the argument list of a wrapper | |
function. | |
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. Namely, F2PY specific attributes can be inserted directly to | |
Fortran source codes using the so-called F2PY directive. A F2PY | |
directive defines special comment lines (starting with ``Cf2py``, for | |
example) which are ignored by Fortran compilers but F2PY interprets | |
them as normal lines. | |
Here is shown a `modified version of the example Fortran code`__, saved | |
as ``fib3.f``: | |
.. include:: fib3.f | |
:literal: | |
__ fib3.f | |
Building the extension module can be now carried out in one command:: | |
f2py -c -m fib3 fib3.f | |
Notice that the resulting wrapper to ``FIB`` is as "smart" as in | |
previous case:: | |
>>> import fib3 | |
>>> print fib3.fib.__doc__ | |
fib - Function signature: | |
a = fib(n) | |
Required arguments: | |
n : input int | |
Return objects: | |
a : rank-1 array('d') with bounds (n) | |
>>> print fib3.fib(8) | |
[ 0. 1. 1. 2. 3. 5. 8. 13.] | |