I would like to use
f2py with modern Fortran. In particular I'm trying to get the following basic example to work. This is the smallest useful example I could generate.
! alloc_test.f90 subroutine f(x, z) implicit none ! Argument Declarations ! real*8, intent(in) :: x(:) real*8, intent(out) :: z(:) ! Variable Declarations ! real*8, allocatable :: y(:) integer :: n ! Variable Initializations ! n = size(x) allocate(y(n)) ! Statements ! y(:) = 1.0 z = x + y deallocate(y) return end subroutine f
n is inferred from the shape of input parameter
x. Note that
y is allocated and deallocated within the body of the subroutine.
When I compile this with
f2py -c alloc_test.f90 -m alloc
And then run in Python
from alloc import f from numpy import ones x = ones(5) print f(x)
I get the following error
ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (-1,)
So I go and create and edit the
pyf file manually
f2py -h alloc_test.pyf -m alloc alloc_test.f90
python module alloc ! in interface ! in :alloc subroutine f(x,z) ! in :alloc:alloc_test.f90 real*8 dimension(:),intent(in) :: x real*8 dimension(:),intent(out) :: z end subroutine f end interface end python module alloc
python module alloc ! in interface ! in :alloc subroutine f(x,z,n) ! in :alloc:alloc_test.f90 integer, intent(in) :: n real*8 dimension(n),intent(in) :: x real*8 dimension(n),intent(out) :: z end subroutine f end interface end python module alloc
Now it runs but the values of the output
z are always
0. Some debug printing reveals that
n has the value
0 within the subroutine
f. I assume that I'm missing some
f2py header magic to manage this situation properly.
More generally what is the best way to link the above subroutine into Python? I'd strongly prefer not to have to modify the subroutine itself.