使用 F2PY 创建 Fortran 扩展模块,自定义签名文件和子程序存储在单独的 Fortran 文件中?

Create a Fortran extension module using F2PY with a custom signature file and subroutines stored in separate Fortran files?

作为练习,我尝试创建一个 python 模块 fibadd1,其中包含一个方法 fibadd。此方法将吃掉一个整数并吐出前 n 个斐波那契数加上 1 的 numpy 数组(即 1、2、2、3,...)。包含此例程的 Fortran 代码是 fib2.f,并使用包含在 fib1.f 中的子例程 FIB。该子例程计算前 N 个斐波那契数。仅使用这两个文件,我就能够使用名为 test2.py 的 python 脚本直接从源代码成功编译给定的例程。但是,在尝试创建自定义 .pyf 签名文件(如 this tutorial 时)时,我遇到了障碍 运行。签名文件名为fib2.pyf.

我能够从命令行使用命令 python -m numpy.f2py -c fib2.pyf fib2.f fib1.f --compiler=mingw32 成功编译和 运行 所有内容。但是,我希望能够使用 numpy.f2py.run_main(...)numpy.f2py.compile(...) 函数在 python 脚本中执行此操作。基于 this documentation 看来它们应该具有相同(或相似)的功能。我试过的脚本叫做 test3.py.

它只是在退出时给出 1。是否可以在 python 脚本中执行此操作?还有比我链接的文档更多的文档吗?我在解析 numpy.f2py.compile 函数时遇到问题。

源码如下:

fib2.f

C FILE: FIB2.F
      SUBROUTINE FIBADD(A,N)
C
C     ADD 1 TO THE FIBONACCI ROUTINE
C
      INTEGER N
      REAL*8 A(N)
      CALL FIB(A, N)
      DO I=1,N
          A(I) = A(I) + 1.0D0
      ENDDO
      END
C END FILE FIB2.F

fib1.f

C FILE: FIB1.F
      SUBROUTINE FIB(A,N)
C
C     CALCULATE FIRST N FIBONACCI NUMBERS
C
      INTEGER N
      REAL*8 A(N)
      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
      RETURN
      END
C END FILE FIB1.F

test2.py

import numpy.f2py
import numpy as np

with open('fib2.f') as file:
    source = file.read()
module = 'fibadd1'
args = ['fib1.f', '--compiler=mingw32']
failure = numpy.f2py.compile(source, modulename=module, 
                             extra_args=args, verbose=False)
print(failure)

import fibadd1
a = np.zeros(8, 'd')
fibadd1.fibadd(a)
print(a)

fib2.pyf

!    -*- f90 -*-
! Note: the context of this file is case sensitive.

python module fib2
    interface
        subroutine fibadd(a,n)
            real*8 dimension(n),intent(out),depend(n) :: a
            integer intent(in) :: n
        end subroutine fibadd
    end interface 
end python module fib2

! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/

test3.py

import numpy.f2py
import numpy as np

with open('fib2.f') as file:
    source = file.read()
module = 'fibadd1'
args = ['fib2.pyf','fib1.f', '--compiler=mingw32']
failure = numpy.f2py.compile(source, modulename=module, 
                             extra_args=args, verbose=False)
print(failure)

事实证明,在修改后的 .pyf 文件中,有两行 python module fib2end python module fib2 指示导入的 python 模块名称(去数字)。为了成功编译,numpy.f2py.compile 函数的 modulename 关键字必须匹配该名称。因此,更正后的.py编译脚本为:

import numpy.f2py

with open('fib2.f') as file:
    source = file.read()
    
module = 'fib2'
args = ['fib2.pyf','fib1.f', '--compiler=mingw32']

failure = numpy.f2py.compile(source, extra_args=args, 
                             modulename=module, verbose=False)
print(failure)

import fib2

a = fib2.fibadd(8)
print(a)