Search code examples
pythonfortranprivatepython-modulef2py

F2py unable to compile module with private functions


I am building a Python module from a Fortran module using f2py. The Fortran module contains private procedures which do not need to be available in the Python module. Here is a code example that reproduces the issue:

module testmodule

  implicit none

  public :: &
       test_sub

  private :: &
       useful_func

contains

  subroutine test_sub()

    !uses the function
    print*, useful_func(3)

  end subroutine test_sub

  function useful_func(in) result(res)
    integer, intent(in) :: in
    integer :: res

    !Does some calculation
    res=in+1

  end function useful_func

end module testmodule

When I compile it with:

f2py -c test.f90 -m test

Compilation fails with the following error message:

gfortran:f90: /tmp/tmpXzt_hf/src.linux-x86_64-2.7/test-f2pywrappers2.f90
/tmp/tmpXzt_hf/src.linux-x86_64-2.7/test-f2pywrappers2.f90:7:28:

       use testmodule, only : useful_func
                            1
Error: Symbol « useful_func » referenced at (1) not found in module « testmodule »

It seems like gfortran is trying to use the private function outside of the module, which of course fails.

Removing the public/private statement solves the problem (by making all the functions public), but I feel like this is not a clean way to do it. These functions are not necessarily meant to be used in Python and should not be available in the Python environment. What if one can't modify a Fortran script that contains such declaration?

In short:

What is a clean way to manage private procedures in Fortran using f2py?


Solution

  • f2py has heuristics to determine what to include in the compiled module. You can make it specific by using the option "only" as in

    f2py -c -m ff ff.f90 only: test_sub
    

    Typing f2py with no option gives you a list of options that is useful. Depending on your needs, you might consider using the iso_c_binding feature of Fortran (2003 and up).