9

I have a Fortran module which I am trying to compile with f2py (listed below). When I remove the module declaration and leave the subroutine in the file by itself, everything works fine. However, if the module is declared as shown below, I get the following results:

> f2py.py -c -m its --compiler=mingw itimes-s2.f
...
Reading fortran codes...
    Reading file 'itimes-s2.f' (format:fix,strict)
crackline: groupcounter=1 groupname={0: '', 1: 'module', 2: 'interface', 3: 'subroutine'}
crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.
...
c:\users\astay13\appdata\local\temp\tmpgh5ag8\Release\users\astay13\appdata\local\temp\tmpgh5ag8\src.win32-3.2\itsmodule.o:itsmodule.c:(.data+0xec): undefined reference to `itimes_'
collect2: ld returned 1 exit status

What is different about compiling a module or subroutine in f2py? Have I left something important out in the module that causes f2py to have trouble? Note that the module compiles fine when I use gfortran alone.

Software: Windows 7; gcc, gfortran 4.6.1 (MinGW); python 3.2.2; f2py v2

itimes-s2.f:

  module its

  contains

  subroutine itimes(infile,outfile)

    implicit none

    ! Constants
    integer, parameter :: dp = selected_real_kind(15)

    ! Subroutine Inputs
    character(*), intent(in) :: infile
    character(*), intent(in) :: outfile

    ! Internal variables
    real(dp) :: num
    integer :: inu
    integer :: outu
    integer :: ios

    inu = 11
    outu = 22

    open(inu,file=infile,action='read')
    open(outu,file=outfile,action='write',access='append')

    do
      read(inu,*,IOSTAT=ios) num
      if (ios < 0) exit

      write(outu,*) num**2
    end do

  end subroutine itimes

  end module its
francescalus
  • 30,576
  • 16
  • 61
  • 96
astay13
  • 6,857
  • 10
  • 41
  • 56

3 Answers3

11

You are trying to have a Fortran module in a Python module. If you want that, the names must be different, e.g.

 f2py.py -c -m SOMEDIFFERENTNAME itimes-s2.f

The result will be called as pythonmodule.fortranmodule.yourfunction().

You can also import it as

from pythonmodule import fortranmodule
fortranmodule.yourfunction()

Otherwise it worked on my machine.

  • I tried running `f2py -c --compiler=mingw32 -m itsm itimes-s2.f` but the error messages are still the same. – astay13 Dec 20 '11 at 15:19
  • Try rename the file to have .f90 suffix. It seems that the compiler assumes it is a fixed format file (at least on my machine). I am using `f2py -c -m itsm itimes-s2.f90` and it works. I tested it on 2 different linux computers. – Vladimir F Героям слава Dec 20 '11 at 20:54
  • 1
    Thanks Vladimir! Once I renamed it to a `.f90` extension it worked great, even if the Python and Fortran modules had the same name. – astay13 Dec 20 '11 at 21:50
  • Could we make the fortran module into a single level python module to be used like `module.function()`? – Jonatan Öström Jul 29 '18 at 23:23
2

For f2py to work you need to have a signature file to direct the interface creation or modify your source code with f2py comments to help with the interface. See https://numpy.org/doc/stable/f2py/signature-file.html for more information.

From that site:

C FILE: FIB3.F
      SUBROUTINE FIB(A,N)
C
C     CALCULATE FIRST N FIBONACCI NUMBERS
C
      INTEGER N
      REAL*8 A(N)
Cf2py intent(in) n
Cf2py intent(out) a
Cf2py depend(n) a
      DO I=1,N
         IF (I.EQ.1) THEN
            A(I) = 0.0D0
         ELSEIF (I.EQ.2) THEN
            A(I) = 1.0D0
         ELSE 
            A(I) = A(I-1) + A(I-2)
         ENDIF
      ENDDO
      END
C END FILE FIB3.F

Building the extension module can be now carried out in one command:

f2py -c -m fib3 fib3.f
James Chong
  • 371
  • 2
  • 16
WombatPM
  • 2,561
  • 2
  • 22
  • 22
  • Right, but my problem is that f2py works fine when the subroutine is listed by itself in the file, but gives an error when I enclose it in a module. From your link, it seems that I should be able to use my source (perhaps with some additional directives) as my signature file. What additional directives do I need to include so it accepts the module? – astay13 Dec 19 '11 at 18:49
0

To wrap a F90 module with f2py you do need to specify what features can be accessible from outside the module. For that you have the private and public fortran90 keywords. You should also change the extension from .f to .F90 or .f90. I made some changes in your code that demonstrates the use of public and private keywords.

First of all create the signature file that hols the fortran interfaces for the module objects:

f2py -h interface.pyf -m module_name module_its.f90 --overwrite-signature

THen compile the module:

f2py interface.pyf -c module_its.f90 

Your code modified and named as module_its.f90:

module its   
  ! use other modules
  implicit none
  private          ! everything in this module is private by standard 
                   ! (it can be used only inside this F90 module)
  public :: itimes ! Make you subroutine public
 
  contains

  subroutine itimes(infile,outfile)
    ! use other modules here to

    !implicit none holds for everthing in this module

    ! Constants
    integer, parameter :: dp = selected_real_kind(15)

    ! Subroutine Inputs
    character(*), intent(in) :: infile
    character(*), intent(in) :: outfile

    ! Internal variables
    real(dp) :: num
    integer :: inu
    integer :: outu
    integer :: ios

    inu = 11
    outu = 22

    open(inu,file=infile,action='read')
    open(outu,file=outfile,action='write',access='append')

    do
      read(inu,*,IOSTAT=ios) num
      if (ios < 0) exit

      write(outu,*) num**2
    end do

  end subroutine itimes

end module its