call functions from a shared fortran library in python call functions from a shared fortran library in python python python

call functions from a shared fortran library in python


You'll need to know the signatures of the functions in the shared object. Do you have the source code, or some reference which explains the function names and argument types?

For example, I have this source code (mult.f90):

integer function multiply(a, b)    integer, intent(in) :: a, b    multiply = a * bend function multiply

.. and to demonstrate how you can load and use multiple shared objects at once, I also have (add.f90):

integer function addtwo(a, b)    integer, intent(in) :: a, b    addtwo = a + bend function addtwo

Compile, examine symbols:

% gfortran-4.4 -shared -fPIC -g -o mult.so mult.f90% gfortran-4.4 -shared -fPIC -g -o add.so add.f90% nm -ao mult.so | grep multiplymult.so:00000000000005cc T multiply_

Notice the symbol name in the shared object has an underscore appended. Since I have the source, I know that the signature is multiply_(int *a, int *b), so it is easy to invoke that function from ctypes:

from ctypes import byref, cdll, c_intmult = cdll.LoadLibrary('./mult.so')add = cdll.LoadLibrary('./add.so')a = c_int(2)b = c_int(4)print mult.multiply_(byref(a), byref(b))print add.addtwo_(byref(a), byref(b))

Output:

86


I would add to @sameplebias answer, that one can use the iso_c_binding module to force (any) fortran compiler to produce the correct C signature. Example of usage:

module fmesh_wrapperuse iso_c_binding, only: c_double, c_intuse fmesh, only: mesh_expimplicit nonecontainssubroutine c_mesh_exp(r_min, r_max, a, N, mesh) bind(c)real(c_double), intent(in) :: r_minreal(c_double), intent(in) :: r_maxreal(c_double), intent(in) :: ainteger(c_int), intent(in) :: Nreal(c_double), intent(out) :: mesh(N)call mesh_exp(r_min, r_max, a, N, mesh)end subroutine! wrap more functions here! ...end module

this will have the following C signature:

void c_mesh_exp(double *r_min, double *r_max, double *a, int *N,        double *mesh);

and then you can call it from Python as usual. The advantage of this approach is that it works on all platforms (without using any special compiler options).


For f2py (from NumPy) to work, borrow both the mult.f90 and add.f90 examples from @samplebias. From a shell, compile the Python importable shared libraries:

f2py -c -m mult mult.f90f2py -c -m add add.f90

Now use them in Python:

>>> import add>>> import mult>>> add.addtwo(4, 5)9>>> mult.multiply(4, 5)20