9

I cannot get f2py to reference a parameter from a module in a separate subroutine where it is used to defined an input array dimension. I.e. the paramter is defeind in a module:

! File: testmod.f90
MODULE testmod
INTEGER, PARAMETER :: dimsize = 20
END MODULE testmod

and the parameter dimsize needs to be referenced in a subroutine (NOT contained in the module) in another file, which will be the entry point for my python module:

! File testsub.f90
SUBROUTINE testsub(arg)
USE testmod
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

I compile like this:

f2py -m testmod  -h testmod.pyf testsub.f90
pgf90 -g -Mbounds -Mchkptr -c -fPIC testmod.f90 -o testmod.o
pgf90 -g -Mbounds -Mchkptr -c -fPIC testsub.f90 -o testsub.o
f2py -c testmod.pyf testmod.o testsub.o

but get this error:

testmodmodule.c: In function 'f2py_rout_testmod_testsub':
testmodmodule.c:180: error: 'dimsize' undeclared (first use in this function)

I have tried modifying testsub.g90 to include the following directive, as suggested ni other posts:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, parameter :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

but to no avail. I need to keep the subroutine separate from the module.

How can I get f2py to correctly resolve the variable dimsize?

TIA

cm2
  • 1,815
  • 15
  • 20
ccbunney
  • 2,282
  • 4
  • 26
  • 42
  • I am having the same problem with `ifort` on Windows 7, using f2py version 2. The problem seems to occur at the _first_ f2py call, where I see the error: `In: :testmoddd:testsub.f90:testsub get_useparameters: no module testmod info used by testsub In: :testmoddd:testsub.f90:testsub getarrlen:variable "dimsize" undefined` – bdforbes Nov 19 '13 at 01:17
  • @bdforbes: hmmm....I am beginning to think this is just a serious shortcoming of f2py when using Fortran90. I should have stuck to F77! – ccbunney Nov 19 '13 at 09:26

2 Answers2

3

It's been a long time since this question has gotten any activity, but I figured out the problem so I thought I'd post it for anyone else who has this issue. The problem is that while the Fortran code is perfectly valid, the C wrapper generated by F2PY doesn't know what dimsize is when it checks that arrays are the correct size (within the C wrapper, it's encapsulated in some kind of module structure).

Just change this code:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, parameter :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

to this:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, intent(aux) :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

This will "Define auxiliary C variable in F2PY generated wrapper function". As the Scipy docs say, this is "Useful to save parameter values so that they can be accessed in initialization expression of other variables".

I haven't tested this with your code, but I've tested it with a similar situation I was having.

Jeremy McGibbon
  • 3,527
  • 14
  • 22
  • nice! I also had this problem when declaring an array in a subroutine whose dimension used a parameter defined in the *same* module, and this fixed it. – Matt Hancock Mar 07 '17 at 18:14
  • 1
    I am trying to do the same thing. The only difference is `dimsize` is not defined with the `parameter` attribute in the module. F2PY compiles but then when I run the subroutine in python I get an error: `ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (0,)`. Any thoughts? – Alex Sep 13 '18 at 20:02
  • having the same problem, any solution to this? – Eular Oct 10 '19 at 07:54
  • I don't understand what "The only difference is `dimsize` is not defined with the `parameter` attribute in the module" means. Does the same solution with `intent(aux)` not work? Perhaps it is worth opening a new question with these details in a MCVE? – Jeremy McGibbon Oct 14 '19 at 04:27
1

Although I've not tested it, I think you nearly have it with your original code. We do something similar for some of our code, but with gfortran.

You shouldn't need to f2py the testmod.f90 file. You should just compile it to an object file just like you would if this were normal Fortran:

pgf90 -g -Mbounds -Mchkptr -c -fPIC testmod.f90 -o testmod.o

Then you should be able to compile your testsub.f90 into a python-usable module with:

f2py --fcompiler=pgf90 --f90flags="-g -Mbounds -Mchkptr" -c testsub.f90 -m testsub testmod.o

That should build a testsub.so, or equivalent, letting you import testsub and then testsub.testsub(my_arg) in python.

cm2
  • 1,815
  • 15
  • 20
  • Hmmm, have you tried with a different compiler? I've only ever used gfortran with f2py... – cm2 Nov 25 '13 at 18:37
  • 1
    I've tried it again with --fcompiler=gfortran, but I get the same errors. It is essentially the c compiler that is producing the errors, not the fortran compiler. I think that f2py simply does not handle the F90 modules well... – ccbunney Nov 26 '13 at 10:18