F2PY - 从子程序中访问模块参数

9

我无法让f2py引用一个在模块中定义的参数,而该参数在另一个子程序中用于定义输入数组的维度。也就是说,该参数在一个模块中被定义:

! File: testmod.f90
MODULE testmod
INTEGER, PARAMETER :: dimsize = 20
END MODULE testmod

并且需要在另一个文件的子程序(不包含在模块中)中引用参数dimsize,该文件将是我的Python模块的入口点:

! File testsub.f90
SUBROUTINE testsub(arg)
USE testmod
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

我会按照以下方式进行编译:

f2py -m testmod  -h testmod.pyf testsub.f90
pgf90 -g -Mbounds -Mchkptr -c -fPIC testmod.f90 -o testmod.o
pgf90 -g -Mbounds -Mchkptr -c -fPIC testsub.f90 -o testsub.o
f2py -c testmod.pyf testmod.o testsub.o

但是我遇到了下面的错误:

testmodmodule.c: In function 'f2py_rout_testmod_testsub':
testmodmodule.c:180: error: 'dimsize' undeclared (first use in this function)

我尝试修改testsub.g90文件并加入以下指令,这是其他帖子中建议的方法:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, parameter :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

但是没有成功。我需要将子程序与模块分开。

我该如何让f2py正确解析变量dimsize

TIA


我在Windows 7上使用f2py版本2时遇到了与ifort相同的问题。问题似乎发生在第一个f2py调用处,我看到以下错误: In: :testmoddd:testsub.f90:testsub get_useparameters: no module testmod info used by testsub In: :testmoddd:testsub.f90:testsub getarrlen:variable "dimsize" undefined - bdforbes
@bdforbes:嗯……我开始觉得这只是使用Fortran90时f2py的严重缺陷。我应该坚持使用F77! - ccbunney
2个回答

3

这个问题已经很久没有得到任何回复了,但我搞清楚了问题,所以我想为那些遇到这个问题的人发布解决方案。问题在于,尽管Fortran代码完全有效,但由F2PY生成的C包装器在检查数组是否具有正确大小时不知道dimsize是什么(在C包装器中,它被封装在某种模块结构中)。

只需更改此代码:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, parameter :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

转换为:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, intent(aux) :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

这将“在F2PY生成的包装函数中定义辅助C变量”。正如Scipy文档所说,这对于“保存参数值以便可以在其他变量的初始化表达式中访问它们”非常有用。
我没有使用您的代码测试过,但我已经在类似的情况下进行了测试。

太好了!我在子程序中声明一个数组时遇到了同一模块中使用参数定义的维度的问题,这个方法解决了它。 - Matt Hancock
1
我正在尝试做同样的事情。唯一的区别是在模块中,dimsize没有使用parameter属性进行定义。F2PY编译通过,但当我在Python中运行子程序时,出现错误:ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (0,)。有什么想法吗? - Alex
有相同的问题,有解决方案吗? - Eular
我不明白"The only difference is dimsize is not defined with the parameter attribute in the module"的意思。使用intent(aux)的相同解决方案不起作用吗?也许值得在MCVE中提供这些细节并开启一个新问题? - Jeremy McGibbon

1
尽管我没有测试过,但我认为你的原始代码已经非常接近了。我们对一些代码做类似的事情,但使用的是gfortran。
你不需要对testmod.f90文件进行f2py操作。你只需要像普通Fortran一样将其编译为目标文件即可:
pgf90 -g -Mbounds -Mchkptr -c -fPIC testmod.f90 -o testmod.o

那么你应该能够用以下命令将testsub.f90编译成可供Python使用的模块:

f2py --fcompiler=pgf90 --f90flags="-g -Mbounds -Mchkptr" -c testsub.f90 -m testsub testmod.o

这将构建一个testsub.so或等效物,让您可以在Python中import testsub,然后testsub.testsub(my_arg)


嗯,你尝试过使用不同的编译器吗?我只用过gfortran和f2py... - cm2
1
我已经尝试了--fcompiler = gfortran,但是我得到了相同的错误。实际上是C编译器产生了错误,而不是Fortran编译器。我认为f2py不能很好地处理F90模块... - ccbunney

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