call functions from a shared fortran library in python

前端 未结 3 1332
被撕碎了的回忆
被撕碎了的回忆 2020-12-23 15:19

I would like to call some functions from a Fortran shared library in Python. I have found some links on the net and read them, and according what I found, I should do

<
相关标签:
3条回答
  • 2020-12-23 15:47

    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_wrapper
    
    use iso_c_binding, only: c_double, c_int
    use fmesh, only: mesh_exp
    
    implicit none
    
    contains
    
    subroutine c_mesh_exp(r_min, r_max, a, N, mesh) bind(c)
    real(c_double), intent(in) :: r_min
    real(c_double), intent(in) :: r_max
    real(c_double), intent(in) :: a
    integer(c_int), intent(in) :: N
    real(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).

    0 讨论(0)
  • 2020-12-23 15:55

    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 * b
    end 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 + b
    end 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 multiply
    mult.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_int
    
    mult = 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:

    8
    6
    
    0 讨论(0)
  • 2020-12-23 16:03

    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.f90
    f2py -c -m add add.f90
    

    Now use them in Python:

    >>> import add
    >>> import mult
    >>> add.addtwo(4, 5)
    9
    >>> mult.multiply(4, 5)
    20
    
    0 讨论(0)
提交回复
热议问题