在Fortran模块中使用全局常量时,我发现f2py有一些奇怪的行为。
假设我有一个文件test.f90,看起来像是
module test1
real, parameter :: a = 12345.
end module test1
module test2
real*8, parameter :: a = 6789.
end module test2
如果我用f2py使用
包装它f2py -c -m mymod test.f90
并正在运行
python -c "import mymod as m; print m.test1.a; print m.test2.a"
我得到了
12345.0
6789.0
这几乎是你所期待的。真实和真实* 8语句的行为方式相同。
对于我的实际项目,我需要使用编译器标志编译我的Fortran代码,指定双精度的显式用法。在Fortran中,这很好用。当我将上面的代码编译为
时f2py --f90flags="-fdefault-double-8 -fdefault-integer-8 -fdefault-real-8" -c -m mymod test.f90
我得到了结果
python -c "import mymod as m; print m.test1.a; print m.test2.a"
0.0
6789.0
这实际上很奇怪。全局变量在第一种情况下未初始化,它的值为零。这是一个错误,还是有不同的方法来指定f2py中双精度的显式处理?
答案 0 :(得分:1)
你没有指定“显式使用双精度” - 我认为你指的是“隐式使用双精度”而numpy / f2py无法知道数据类型。在这种情况下,f2py可能猜测数据类型是float32,因此实际上只解释了(64位)参数的前32位。如果将双精度数传递给期望浮点函数的函数,则可以看到相同的效果:
program main
real*8 :: foo
foo = 12345.
call printme(foo)
end program
subroutine printme(foo)
real foo
print*, foo
end subroutine printme
编译并运行:
gfortran test2.f90
./a.out #prints 0.00000
这里的内容是,您期望f2py
知道如何解释fortran代码以及如何解释特定编译器的命令行参数。我们或许可以说这种类型的支持对一小组编译器很有用 - 不幸的是,目前f2py
不支持它。
您需要将所有参数和参数声明为特定类型,并在命令行中更改它们可能会导致您在上面看到的各种错误。
答案 1 :(得分:0)
到目前为止我找到了一个解决方法。问题是,当提供适当的双精度编译器标志时,f2py无法识别它应该将fortran real
映射到C类型double
。
解决方案是明确告诉f2py如何映射不同的数据类型。这可以通过创建文件.f2py_f2cmap
来实现,该文件包含指定数据类型映射的python字典。有关详细信息,请参阅here。
在我的情况下,以下条目解决了问题
{'real':{'':'double'},'integer':{'':'long'},'real*8':{'':'double'}}