使用f2py编译Fortran模块

10

我有一个Fortran模块,我正在尝试使用f2py编译它(如下所示)。当我删除模块声明并将子程序留在文件中时,一切都运行良好。然而,如果像下面所示那样声明模块,则会得到以下结果:

> 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

在f2py中编译模块或子程序有何不同?我在模块中漏掉了什么重要的内容导致f2py出现问题吗?请注意,当我仅使用gfortran时,该模块可以正常编译。

软件: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
3个回答

12

您正在尝试在Python模块中使用Fortran模块。如果您想要这样做,名称必须不同,例如:

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

结果将被称为pythonmodule.fortranmodule.yourfunction()

你也可以这样导入它:

from pythonmodule import fortranmodule
fortranmodule.yourfunction()

否则它在我的电脑上可以运行。


我尝试运行 f2py -c --compiler=mingw32 -m itsm itimes-s2.f,但错误信息仍然相同。 - astay13
尝试将文件重命名为.f90后缀。看起来编译器假定它是一个固定格式的文件(至少在我的机器上是这样)。我正在使用f2py -c -m itsm itimes-s2.f90,它可以正常工作。我在两台不同的Linux计算机上进行了测试。 - Vladimir F Героям слава
1
谢谢Vladimir!一旦我将它重命名为.f90扩展名,它就非常好用了,即使Python和Fortran模块具有相同的名称。 - astay13
我们是否可以将Fortran模块转换为单层Python模块以便像module.function()一样使用? - Jonatan Öström

3
要使f2py正常工作,您需要有一个签名文件来指导接口的创建,或者使用f2py注释修改源代码以帮助接口。请参阅https://numpy.org/doc/stable/f2py/signature-file.html获取更多信息。
从该网站上可以看到:
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

现在可以通过一个命令来构建扩展模块:
f2py -c -m fib3 fib3.f

没错,但我的问题是当子程序单独列在文件中时,f2py可以正常工作,但当我将其封装在模块中时会出现错误。从您提供的链接中,似乎我应该能够使用我的源代码(可能需要一些额外的指令)作为签名文件。我需要包含哪些额外的指令才能使其接受模块? - astay13

1

使用f2py包装F90模块时,您需要指定可以从模块外部访问的功能。为此,您可以使用私有和公共Fortran90关键字。您还应将扩展名从.f更改为.F90或.f90。我对您的代码进行了一些更改,以演示publicprivate关键字的使用。

首先创建签名文件,其中包含模块对象的Fortran接口:

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

然后编译模块:

f2py interface.pyf -c module_its.f90 

您的代码已修改并命名为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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接