我试图用Python包装一个相当大的Fortran库。我可以修改源代码,但显然想尽可能少地修改。代码中定义了许多固定大小的数组,其中较低和/或较高的索引由较低级别模块的参数指定。所以它可能有像
这样的陈述use parrrsw, only : j1, j2
integer(kind=4), intent(in), dimension(j1:j2) :: opt_depth
在试图弄清楚如何使用f2py来适应这个时,我创建了以下最小的例子以显示我已经得到的错误。从本质上讲,似乎f2py可以识别从rrsw
导入的索引,但是如果它们也用于初始化数组,则无法使用它们分配给数组。我想我可能会使用f2py的depend
声明错误,但我还没有找到一个可以帮我修复它的例子。
(实际上,大多数数组最初被定义为可分配但稍后用参数填充。这完全是另一个问题......但是如果有人有一个很好的方法来适应代码的话以这种方式系统地写下来,我很乐意听到它。)
编辑2016-06-13:我决定尝试使用CFFI或ctypes来进行模块导入。这个问题仍然存在,但它对我的工作不再重要。
示例代码:
test_rrsw.f90:
module test_rrsw
implicit none
integer, parameter :: im = selected_int_kind(6)
integer(kind=im), parameter :: jpb1=16, jpb2=20
integer(kind=im), parameter :: ng16=6, ng17=12, ng18=8, ng19=8, ng20=10
end module test_rrsw
test_minimal.f90:
module test_minimal
implicit none
integer, parameter :: im = selected_int_kind(6)
integer, parameter :: rb = selected_real_kind(12)
contains
subroutine test_pars1(ng)
use test_rrsw, only : jpb1, jpb2, ng16, ng17, ng18, ng19, ng20
implicit none
!f2py integer intent(out) :: ng(16:20)
integer(kind=im), intent(out), dimension(16:20) :: ng
ng(jpb1:jpb2) = (/ ng16, ng17, ng18, ng19, ng20 /)
end subroutine test_pars1
subroutine test_pars2(ng)
use test_rrsw, only : jpb1, jpb2, ng16, ng17, ng18, ng19, ng20
implicit none
!f2py integer intent(aux) :: jpb1, jpb2
!f2py depend(jpb1,jpb2) :: ng
!f2py integer intent(out) :: ng(jpb1:jpb2)
integer(kind=im), intent(out), dimension(jpb1:jpb2) :: ng
write(*,*) jpb1, jpb2
ng(jpb1:jpb2) = (/ ng16, ng17, ng18, ng19, ng20 /)
end subroutine test_pars2
end module test_minimal
test.py:
#!/usr/bin/env python
import test_minimal
res1 = test_minimal.test_minimal.test_pars1()
res2 = test_minimal.test_minimal.test_pars2()
print 'pars1 =', res1, ' pars2 =', res2
run_test.sh:
#!/usr/bin/env bash
gfortran -c test_rrsw.f90
gfortran -c test_minimal.f90
f2py -c test_minimal.f90 test_rrsw.o -m test_minimal > log_f2py.txt
python test.py
使用./run_test.sh
生成输出,从Python调用两个不同的子例程test_pars1
和test_pars2
。 (警告:在运行这些例程后退出 Python时,有时会出现段错误。)如果其中任何一个不适合您,请告诉我。这是很多代码,但我想尽可能明确地编译/链接/测试。