Question

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
Was it helpful?

Solution

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.

OTHER TIPS

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 http://cens.ioc.ee/projects/f2py2e/usersguide/#signature-file 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

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top