Self-written 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
usercode
pymethoddef
python module
spam.pyf
! -*- f90 -*- python module spam usercode ''' static char doc_spam_system[] = "Execute a shell command."; static PyObject *spam_system(PyObject *self, PyObject *args) { char *command; int sts; if (!PyArg_ParseTuple(args, "s", &command)) return NULL; sts = system(command); return Py_BuildValue("i", sts); } ''' pymethoddef ''' {"system", spam_system, METH_VARARGS, doc_spam_system}, ''' end python module spam
wraps the C library function system():
system()
f2py -c spam.pyf
In Python:
>>> import spam >>> status = spam.system('whoami') pearu >>> status = spam.system('blah') sh: line 1: blah: command not found
The following example illustrates how to add user-defined variables to a F2PY generated extension module. Given the following signature file
! -*- f90 -*- python module var usercode ''' int BAR = 5; ''' interface usercode ''' PyDict_SetItemString(d,"BAR",PyInt_FromLong(BAR)); ''' end interface end python module
compile it as f2py -c var.pyf.
f2py -c var.pyf
Notice that the second usercode statement must be defined inside an interface block and where the module dictionary is available through the variable d (see f2py var.pyf-generated varmodule.c for additional details).
interface
d
f2py var.pyf
varmodule.c
>>> import var >>> var.BAR 5
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.
<type spec>(kind=<kindselector>)
<kindselector>
KIND(..)
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.
--f2cmap
.f2py_f2cmap
Or 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>. <C type> can be one of the following:
char signed_char short int long_long float double long_double complex_float complex_double complex_long_double string
For more information, see F2Py source code numpy/f2py/capi_maps.py.
numpy/f2py/capi_maps.py
numpy.distutils