当子例程包含内部过程时,f2py 给出错误(但使用 gfortran 编译成功)
f2py gives error when subroutine contains internal procedures (but compiles successfully with gfortran)
以下程序在子例程不包含任何内部过程时编译(在 f2py 中)但在包含任何内部过程时无法在 f2py 中编译(使用 gfortran 编译)
Fortran 代码:
subroutine example(array)
implicit none
real*8::array(:,:)
INTEGER::i,j
!f2py intent(inout)::array
do i=1,3
do j=1,3
array(i,j)=10*i+j
enddo
! print*,''
enddo
call tentimes(array)
RETURN
contains
subroutine tentimes(array)
implicit none
!f2py intent(inout):array
real*8::array(:,:)
array=array*10
end subroutine tentimes
end subroutine example
program dummy
implicit none
end program dummy
编译为 python -m numpy.f2py -c allocate.f90 -m ftest
和 python 代码:
import numpy as np
a=np.zeros((3,3),order="F")
print(a)
res=ftest.example(a)
print(a)
为什么会这样?
f2py 生成的错误:
compiling Fortran sources
Fortran f77 compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -fPIC -O3 -funroll-loops
Fortran f90 compiler: /usr/bin/gfortran -Wall -g -fno-second-underscore -fPIC -O3 -funroll-loops
Fortran fix compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -Wall -g -fno-second-underscore -fPIC -O3 -funroll-loops
compile options: '-I/tmp/tmpwd_qygau/src.linux-x86_64-3.9 -I/home/srj/.local/lib/python3.9/site-packages/numpy/core/include -I/usr/include/python3.9 -c'
gfortran:f90: allocate.f90
allocate.f90:17:31:
17 | subroutine tentimes(array_i)
| 1
Warning: Unused dummy argument ‘array_i’ at (1) [-Wunused-dummy-argument]
allocate.f90:17:23:
17 | subroutine tentimes(array_i)
| ^
Warning: ‘tentimes’ defined but not used [-Wunused-function]
gfortran:f90: /tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90
/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90:13:17:
13 | subroutine tentimes(array_i)
| 1
Error: Unclassifiable statement at (1)
/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90:15:39:
15 | end subroutine tentimes
| 1
Error: Expected label ‘example’ for END SUBROUTINE statement at (1)
/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90:14:53:
14 | real*8, dimension(:,:) :: array_i
| 1
Error: Array ‘array_i’ at (1) cannot have a deferred shape
error: Command "/usr/bin/gfortran -Wall -g -fno-second-underscore -fPIC -O3 -funroll-loops -I/tmp/tmpwd_qygau/src.linux-x86_64-3.9 -I/home/srj/.local/lib/python3.9/site-packages/numpy/core/include -I/usr/include/python3.9 -c -c /tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90 -o /tmp/tmpwd_qygau/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.o" failed with exit status 1
类似的嵌套过程在 gfortran 中运行良好。为什么会出现这个错误?如何纠正?
编辑:使用 f2py 的更好方法是“the smart way”
这样做效果很好
python -m numpy.f2py allocate.f90 -m ftest -h ftest.pyf && \
python -m numpy.f2py -c ftest.pyf allocate.f90
因为这会绕过生成 FORTRAN 接口。
好的,我确认是f2py的bug,f2pywrappers2.f90中生成的代码有错误
f2py 产生:
! -*- f90 -*-
! This file is autogenerated with f2py (version:1.21.2)
! It contains Fortran 90 wrappers to fortran functions.
subroutine f2pywrapexample (array, f2py_array_d0, f2py_array_d1)
integer f2py_array_d0
integer f2py_array_d1
real*8 array(f2py_array_d0,f2py_array_d1)
interface
subroutine example(array)
real*8, dimension(:,:),intent(inout) :: array
subroutine tentimes(array)
real*8, dimension(:,:) :: array
end subroutine tentimes
end subroutine example
end interface
call example(array)
end
正确代码:
subroutine f2pywrapexample (array, f2py_array_d0, f2py_array_d1)
integer f2py_array_d0
integer f2py_array_d1
real*8 array(f2py_array_d0,f2py_array_d1)
interface
subroutine example(array)
real*8, dimension(:,:),intent(inout) :: array
end subroutine example
subroutine tentimes(array)
real*8, dimension(:,:) :: array
end subroutine tentimes
end interface
call example(array)
end
接口实际上不应包含嵌套过程,即使子例程具有嵌套过程
解决这个问题,然后生成相应的对象,将其放在正确的临时文件夹中并手动链接到命令
/usr/bin/gfortran -Wall -g -Wall -g -shared /tmp/tmpfw0ammli/tmp/tmpfw0ammli/src.linux-x86_64-3.9/ftestmodule.o /tmp/tmpfw0ammli/tmp/tmpfw0ammli/src.linux-x86_64-3.9/fortranobject.o /tmp/tmpfw0ammli/allocate.o /tmp/tmpfw0ammli/tmp/tmpfw0ammli/src.linux-x86_64-3.9/ftest-f2pywrappers2.o -L/usr/lib/gcc/x86_64-redhat-linux/11 -L/usr/lib/gcc/x86_64-redhat-linux/11 -L/usr/lib64 -lgfortran -o ./ftest.cpython-39-x86_64-linux-gnu.so
这成功了,python 打印了正确的输出。
以下程序在子例程不包含任何内部过程时编译(在 f2py 中)但在包含任何内部过程时无法在 f2py 中编译(使用 gfortran 编译)
Fortran 代码:
subroutine example(array)
implicit none
real*8::array(:,:)
INTEGER::i,j
!f2py intent(inout)::array
do i=1,3
do j=1,3
array(i,j)=10*i+j
enddo
! print*,''
enddo
call tentimes(array)
RETURN
contains
subroutine tentimes(array)
implicit none
!f2py intent(inout):array
real*8::array(:,:)
array=array*10
end subroutine tentimes
end subroutine example
program dummy
implicit none
end program dummy
编译为 python -m numpy.f2py -c allocate.f90 -m ftest
和 python 代码:
import numpy as np
a=np.zeros((3,3),order="F")
print(a)
res=ftest.example(a)
print(a)
为什么会这样?
f2py 生成的错误:
compiling Fortran sources
Fortran f77 compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -fPIC -O3 -funroll-loops
Fortran f90 compiler: /usr/bin/gfortran -Wall -g -fno-second-underscore -fPIC -O3 -funroll-loops
Fortran fix compiler: /usr/bin/gfortran -Wall -g -ffixed-form -fno-second-underscore -Wall -g -fno-second-underscore -fPIC -O3 -funroll-loops
compile options: '-I/tmp/tmpwd_qygau/src.linux-x86_64-3.9 -I/home/srj/.local/lib/python3.9/site-packages/numpy/core/include -I/usr/include/python3.9 -c'
gfortran:f90: allocate.f90
allocate.f90:17:31:
17 | subroutine tentimes(array_i)
| 1
Warning: Unused dummy argument ‘array_i’ at (1) [-Wunused-dummy-argument]
allocate.f90:17:23:
17 | subroutine tentimes(array_i)
| ^
Warning: ‘tentimes’ defined but not used [-Wunused-function]
gfortran:f90: /tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90
/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90:13:17:
13 | subroutine tentimes(array_i)
| 1
Error: Unclassifiable statement at (1)
/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90:15:39:
15 | end subroutine tentimes
| 1
Error: Expected label ‘example’ for END SUBROUTINE statement at (1)
/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90:14:53:
14 | real*8, dimension(:,:) :: array_i
| 1
Error: Array ‘array_i’ at (1) cannot have a deferred shape
error: Command "/usr/bin/gfortran -Wall -g -fno-second-underscore -fPIC -O3 -funroll-loops -I/tmp/tmpwd_qygau/src.linux-x86_64-3.9 -I/home/srj/.local/lib/python3.9/site-packages/numpy/core/include -I/usr/include/python3.9 -c -c /tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.f90 -o /tmp/tmpwd_qygau/tmp/tmpwd_qygau/src.linux-x86_64-3.9/ftest-f2pywrappers2.o" failed with exit status 1
类似的嵌套过程在 gfortran 中运行良好。为什么会出现这个错误?如何纠正?
编辑:使用 f2py 的更好方法是“the smart way”
这样做效果很好
python -m numpy.f2py allocate.f90 -m ftest -h ftest.pyf && \
python -m numpy.f2py -c ftest.pyf allocate.f90
因为这会绕过生成 FORTRAN 接口。
好的,我确认是f2py的bug,f2pywrappers2.f90中生成的代码有错误
f2py 产生:
! -*- f90 -*-
! This file is autogenerated with f2py (version:1.21.2)
! It contains Fortran 90 wrappers to fortran functions.
subroutine f2pywrapexample (array, f2py_array_d0, f2py_array_d1)
integer f2py_array_d0
integer f2py_array_d1
real*8 array(f2py_array_d0,f2py_array_d1)
interface
subroutine example(array)
real*8, dimension(:,:),intent(inout) :: array
subroutine tentimes(array)
real*8, dimension(:,:) :: array
end subroutine tentimes
end subroutine example
end interface
call example(array)
end
正确代码:
subroutine f2pywrapexample (array, f2py_array_d0, f2py_array_d1)
integer f2py_array_d0
integer f2py_array_d1
real*8 array(f2py_array_d0,f2py_array_d1)
interface
subroutine example(array)
real*8, dimension(:,:),intent(inout) :: array
end subroutine example
subroutine tentimes(array)
real*8, dimension(:,:) :: array
end subroutine tentimes
end interface
call example(array)
end
接口实际上不应包含嵌套过程,即使子例程具有嵌套过程
解决这个问题,然后生成相应的对象,将其放在正确的临时文件夹中并手动链接到命令
/usr/bin/gfortran -Wall -g -Wall -g -shared /tmp/tmpfw0ammli/tmp/tmpfw0ammli/src.linux-x86_64-3.9/ftestmodule.o /tmp/tmpfw0ammli/tmp/tmpfw0ammli/src.linux-x86_64-3.9/fortranobject.o /tmp/tmpfw0ammli/allocate.o /tmp/tmpfw0ammli/tmp/tmpfw0ammli/src.linux-x86_64-3.9/ftest-f2pywrappers2.o -L/usr/lib/gcc/x86_64-redhat-linux/11 -L/usr/lib/gcc/x86_64-redhat-linux/11 -L/usr/lib64 -lgfortran -o ./ftest.cpython-39-x86_64-linux-gnu.so
这成功了,python 打印了正确的输出。