User-defined Python C/API functions can be defined inside
signature files using usercode
and pymethoddef
statements
(they must be used inside the python module
block). For
example, the following signature file spam.pyf
wraps the C library function system()
:
f2py -c spam.pyf
In Python this can then be used as:
.. literalinclude:: ./code/results/spam_session.dat :language: python
The following example illustrates how to add user-defined variables to a F2PY
generated extension module by modifying the dictionary of a F2PY generated
module. Consider the following signature file (compiled with f2py -c var.pyf
):
.. literalinclude:: ./code/var.pyf :language: fortran
Notice that the second usercode
statement must be defined inside
an interface
block and the module dictionary is available through
the variable d
(see varmodule.c
generated by f2py var.pyf
for
additional details).
Usage in Python:
.. literalinclude:: ./code/results/var_session.dat :language: python
Currently, F2PY can handle only <type spec>(kind=<kindselector>)
declarations where <kindselector>
is a numeric integer (e.g. 1, 2,
4,...), but not a function call KIND(..)
or any other
expression. F2PY needs to know what would be the corresponding C type
and a general solution for that would be too complicated to implement.
However, F2PY provides a hook to overcome this difficulty, namely, users can define their own <Fortran type> to <C type> maps. For example, if Fortran 90 code contains:
REAL(kind=KIND(0.0D0)) ...
then create a mapping file containing a Python dictionary:
{'real': {'KIND(0.0D0)': 'double'}}
for instance.
Use the --f2cmap
command-line option to pass the file name to F2PY.
By default, F2PY assumes file name is .f2py_f2cmap
in the current
working directory.
More generally, the f2cmap file must contain a dictionary with items:
<Fortran typespec> : {<selector_expr>:<C type>}
that defines mapping between Fortran type:
<Fortran typespec>([kind=]<selector_expr>)
and the corresponding <C type>. The <C type> can be one of the following:
double float long_double char signed_char unsigned_char short unsigned_short int long long_long unsigned complex_float complex_double complex_long_double string
For more information, see F2Py source code numpy/f2py/capi_maps.py
.
In Fortran, assumed length character string arguments are declared as
character*(*)
or character(len=*)
, that is, the length of such
arguments are determined by the actual string arguments at runtime.
For intent(in)
arguments, this lack of length information poses no
problems for f2py to construct functional wrapper functions. However,
for intent(out)
arguments, the lack of length information is
problematic for f2py generated wrappers because there is no size
information available for creating memory buffers for such arguments
and F2PY assumes the length is 0. Depending on how the length of
assumed length character strings are specified, there exist ways to
workaround this problem, as exemplified below.
If the length of the character*(*)
output argument is determined
by the state of other input arguments, the required connection can be
established in a signature file or within a f2py-comment by adding an
extra declaration for the corresponding argument that specifies the
length in character selector part. For example, consider a Fortran
file asterisk1.f90
:
Compile it with f2py -c asterisk1.f90 -m asterisk1
and then in Python:
Notice that the extra declaration character(f2py_len=12) s
is
interpreted only by f2py and in the f2py_len=
specification one
can use C-expressions as a length value.
In the following example:
the length of output assumed length string depends on an input
argument n
, after wrapping with F2PY, in Python: