【问题标题】:Compile Fortran module with f2py使用 f2py 编译 Fortran 模块
【发布时间】:2021-02-19 02:38:07
【问题描述】:

我有一个 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);蟒蛇3.2.2; f2py v2

times-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

【问题讨论】:

    标签: python fortran f2py


    【解决方案1】:

    您正试图在 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,但错误消息仍然相同。
    • 尝试将文件重命名为 .f90 后缀。似乎编译器假定它是一个固定格式的文件(至少在我的机器上)。我正在使用f2py -c -m itsm itimes-s2.f90,它可以工作。我在 2 台不同的 linux 计算机上对其进行了测试。
    • 谢谢弗拉基米尔!一旦我将它重命名为 .f90 扩展名,它就可以很好地工作,即使 Python 和 Fortran 模块具有相同的名称。
    • 我们能不能把fortran模块变成一个单级python模块,像module.function()一样使用?
    【解决方案2】:

    要使 f2py 工作,您需要有一个签名文件来指导界面创建或使用 f2py cmets 修改源代码以帮助界面。请参阅http://cens.ioc.ee/projects/f2py2e/usersguide/#signature-file 了解更多信息。

    从那个网站:

    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 工作正常,但是当我将它包含在模块中时会出错。从您的链接看来,我应该能够使用我的源代码(也许还有一些额外的指令)作为我的签名文件。我需要包含哪些额外的指令才能接受模块?
    【解决方案3】:

    要使用 f2py 包装 F90 模块,您需要指定可以从模块外部访问的功能。为此,您有 private 和 public 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2016-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多