如何才能正确运行从numpy的文档f2py例子吗?

问题描述 投票:1回答:1

我有以下关于f2py和回调函数的examples shown in the numpy docs的一个麻烦。我所执行的确切相同的步骤,在第一个例子(即f2py -c -m callback callback.f)来包装callback.f

C FILE: CALLBACK.F
      SUBROUTINE FOO(FUN,R)
      EXTERNAL FUN
      INTEGER I
      REAL*8 R
Cf2py intent(out) r
      R = 0D0
      DO I=-5,5
         R = R + FUN(I)
      ENDDO
      END
C END OF FILE CALLBACK.F

然而,测试结果作为例子,给我:

python
>>> import callback
>>> def f(i): return i*i
... 
>>> print callback.foo(f)
0.0

因此,返回的0.0代替110.0,其中0.0r在Fortran代码的初始值。不管我用哪个回调函数,结果仍然相同(不变R)。我使用的是从python 3.7获得numpyconda的最新版本。

你可以重现这个问题,还是我做错了什么?

python numpy fortran f2py
1个回答
2
投票

这个问题似乎由预期的和实际的数据类型的外部函数FUN之间的失配引起的:

  • 按照qazxsw POI,在qazxsw POI,该POI qazxsw功能implicit data typing rules of Fortran有一个隐式类型CALLBACK.F(因为没有明确的类型,或EXTERNAL语句)。
  • 然而,也看FUN,其中F2PY包装是明确创建使用REAL的细节,你会注意到,外部函数IMPLICIT NONE的结果second example in the documentation被定义为具有类型f2py -m callback2 -h callback2.pyf callback.f(这也适用于未修改r签名文件,所以这是默认F2PY行为)。

总之问题是,fun预计real*8 :: r返回一个callback2.pyf结果,当从Python和F2PY包装纸侧的外部函数定义返回一个FOO结果。因此,一个解决方案是确保FUN在Fortran和Python的/ F2PY包装相同的返回类型。这可以以几种方式通过添加REAL一个数据类型说明REAL*8来实现,例如:

FUN

包装用REAL*8 FUN如示例中该修改CALLBACK.F,现在得到所需的输出:

C FILE: CALLBACK.F
      SUBROUTINE FOO(FUN,R)
      REAL*8 FUN
      EXTERNAL FUN
      INTEGER I
      REAL*8 R
Cf2py intent(out) r
      R = 0D0
      DO I=-5,5
         R = R + FUN(I)
      ENDDO
      END
C END OF FILE CALLBACK.F

对于利益起见,可以在纯Fortran语言使用两个文件CALLBACK.Fpython -m numpy.f2py -c -m callback callback.f生产,你在Python / F2PY看到相同的行为:

python
>>> import callback
>>> def f(i): return i*i
...
>>> print(callback.foo(f))
110.0

prog.f

使用fun.f编译,它提供了以下输出(实际上与您的问题的Python的例子):

C FILE: PROG.F, including subroutine FOO previously in CALLBACK.F
      PROGRAM MAIN
C     REAL*8 FUN
      EXTERNAL FUN
      REAL*8 R

      R = 0
      PRINT *, "BEFORE: ", R
      CALL FOO(FUN, R)
      PRINT *, "AFTER: ", R

      END

C This is copied from CALLBACK.F 
      SUBROUTINE FOO(FUN,R)
C     REAL*8 FUN
      EXTERNAL FUN
      INTEGER I
      REAL*8 R
Cf2py intent(out) r
      R = 0D0
      DO I=-5,5
         R = R + FUN(I)
      ENDDO
      END
C END OF FILE CALLBACK.F

在取消在C FILE: FUN.F containing the function to be called by FOO REAL*8 FUNCTION FUN(I) INTEGER I FUN = I*I END 和重新编译gfortran -fcheck=all -Wall -g func.f prog.f的两个实例解决了这个问题:

./a.out
 BEFORE:    0.0000000000000000
 AFTER:    0.0000000000000000
© www.soinside.com 2019 - 2024. All rights reserved.