fffi
is a tool to transparently use shared libraries generated by Fortran in
Python with NumPy arrays. It is based on CFFI and currently assumes the use of
gfortran or Intel Fortran.
The focus of fffi
is dynamical automatic generation of interfaces directly
within Python with a minimum of extra code generation and files to allow
for the simplest possible workflow for fast prototyping of Python/Fortran codes.
In this sense it complements F2x which
instead supplies interfaces based on generated code and ISO C bindings.
Both tools aim to be more powerful and flexible alternatives to F2Py
.
The following example can be found in tests/01_arrays
directory and shows
basic usage using CFFI (fast) API mode with a shared library
libtest_arrays.so
containing a module mod_arrays
:
- Import fffi and initialize
fortran_module
objectmod_arrays
from fffi import FortranModule
mod_arrays = FortranModule('test_arrays', 'mod_arrays')
- Define and generate Python extension (only on first run or if library routines have been added/changed)
mod_arrays.fdef("""
subroutine test_vector(vec)
double precision, dimension(:) :: vec
end
subroutine test_array_2d(arr)
double precision, dimension(:,:) :: arr
end
""")
mod_arrays.compile()
Internally, C function headers are generated for CFFI with the required representation of array descriptors by the used Fortran compiler.
- Load interface module to library
mod_arrays.load()
- Calling of a subroutine
test_vector
inmod_arrays
is as simple as
vec = np.ones(15)
mod_arrays.test_vector(vec)
The general workflow to extend such a test is:
- Possibly add new testing routines to
mod_arrays.f90
andtest_arrays.f90
- Run
make
. This generates a shared librarylibtest_arrays.so
and a Fortran executabletest_arrays.x
for reference output - Edit and run
test1_arrays.py
Current status:
- Code generation and invocation is transparent by encapsulation in Python class
- CFFI API mode is used (pre-generate C extension module as a wrapper)
- Subroutine signature definition in Fortran via
fdef
like CFFIcdef
- Array descriptor structs are working with gfortran 5, 6, 7, 8, 9 and Intel Fortran 18
Next steps:
- Add flexibility with regard to types, floating-point precision, etc.
- More testing, in particular with Intel compiler
- Test numpy.array views on existing data and memory management behavior
- Allow for ABI mode in addition to API mode, and static library API mode
- Add support and PGI compiler
- Test in real world applications