I have a Fortran subroutine that I would like to use in Python.
subroutine create_hist(a, n, dr, bins, hist)
integer, intent(in) :: n
real(8), intent(in) :: a(n)
real(8), intent(in) :: dr
integer, intent(out), allocatable :: hist(:)
real(8), intent(out), allocatable :: bins(:)
n_b = n_bins(a, n, dr) ! a function calculating the number of bins
allocate(bins(n_b+1))
allocate(hist(n_b))
hist = 0
!... Create the histogram hist by putting elems of a into bins
end subroutine
It is a simple programme to get an array of numbers a
and create a histogram based on given bin size dr
. First, it gets the number of bins using function n_bins
and then accordingly allocates the space for the arrays bins
and hist
.
While gfortran
compiles this code fine, f2py
raises an error:
/tmp/tmpY5badz/src.linux-x86_64-2.6/mat_ops-f2pywrappers2.f90:32.37:
call create_hist_gnu(a, n, dr, bins, hist)
Error: Actual argument for 'bins' must be ALLOCATABLE at (1)
As I understand it, f2py
does not tolerate allocating space for arrays at runtime (no idea why, as this seems to be a natural scientific need).
Could anyone please suggest a way to allocate Fortran arrays at run-time so that f2py
is happy with that?
As far as I know f2py does not support dummy arguments (sometimes known as function parameters) which have the attribute ALLOCATABLE
. An alternative would be to make it a large enough explicit shape array. You would then use just a certain part of the array.
subroutine create_hist(a, n, dr, n_b_max, bins, hist)
integer, intent(in) :: n
real(8), intent(in) :: a(n)
real(8), intent(in) :: dr
integer, intent(in) :: n_b_max
integer, intent(out) :: hist(n_b_max)
real(8), intent(out) :: bins(n_b_max+1)
By the way, using real(8)
is not a portable way how to specify 64-bit precision and will fail with certain compilers. Even good old double precision
is better as it will always compile to something and often to 64 bit.