Short answer and workaround
The root cause of the problem is related the use of assumed-shape dummy arguments (i.e. arr
) in your functions. Fortran requires such functions to have explicit interfaces. @VladimirF gave an excellent answer to your (related?) question here about just that, indicating that the preferred solution is to put the functions in a module. Assuming your code listing with functions is saved in a file called funcs.f90
, you can simply put them into a module, e.g. called mod_funcs.f90
, like so:
module mod_funcs
implicit none
contains
include "funcs.f90"
end module mod_funcs
Wrap this with F2PY python -m numpy.f2py -m ftest -c mod_funcs.f90
, update the import statement in your python test script to from ftest import mod_funcs as f
and then run it to get the expected result:
3.0
3.0
3.0
3.0
The longer answer and explanation
Fortran function
s are wrapped in subroutine
s by F2PY. In order to support assumed-shape arrays in a Fortran standard compliant way, the F2PY created subroutine wrappers contain interface
s for user defined functions with assumed-shape dummy arguments. You can have a look at these wrappers by specifying a build directory with a --build-dir
flag when wrapping with F2PY, e.g. like this:
python -m numpy.f2py --build-dir .\build -m ftest -c funcs.f90
Looking at the wrapper that is created for the problematic function rsum1
is revealing (I'm copying verbatim from ftest-f2pywrappers.f
keeping F2PY's indentation):
subroutine f2pywraprsum1 (rsum1f2pywrap, arr, f2py_arr_d0)
integer f2py_arr_d0
real(8) arr(f2py_arr_d0)
real(8) rsum1f2pywrap
interface
function rsum1(arr)
real(8), dimension(:),intent(in) :: arr
end function rsum1
end interface
rsum1f2pywrap = rsum1(arr)
end
Note that due to implicit data typing rules, the interface
for rsum1
implies a function with real
data type, not real(8)
as intended - so there is a data type mismatch in the interface! This explains why the seemingly identical function with an explicit result
statement (rsum3
) returns the correct result in your original example, its result has the correct data type. By good fortune in naming your functions, rsum
has the correct interface. If you change rsum
's name to e.g. isum
, implicit data typing rules in its F2PY subroutine wrapper interface will imply that it has an integer
result, and you will get the following output from your (modified to reflect the name change from fsum
to isum
) python script:
0.0
0.0
3.0
3.0
So to me it appears as if there may be a bug in how F2PY creates interfaces for functions with assumed-shape dummy arguments (which can be bypassed by putting those functions into a module directly, or by explicitly declaring return value of the function using result
).
For completeness, I was using Python 3.6.3 :: Intel Corporation
, with NumPy 1.14.3
, and GNU Fortran (GCC) 8.2.0
.