4

I got this simple module in Fortran:

test.f90:

module test
   implicit none
contains

   subroutine foo(chid)
      implicit none
      character(len=*),intent(out):: chid          ! char. identifier
      chid = "foo"
   end subroutine foo
end module test

program bar
   use test
   character(len=20) text
   call foo(text)
   write(*,*) text
end program bar

compiling it (on windows) gfortran test.f90 -o test.exe and running it gives, as expected:

 foo

I can also compile it using f2py: c:\Python27\python.exe c:\Python27\Scripts\f2py.py --fcompiler=gnu95 --compiler=mingw32 -c -m test \test.f90

When I run this Python script:

test.py:

from id_map import test

print "This should be 'foo':"
print test.foo()
print "was it?"

I get the following output:

This should be 'foo':

was it?

As you can see, the string that should be "foo" is empty. Why is this?

1 Answer 1

5

The problem here is with the len=* character declaration. you're telling the fortran compiler to accept any length string which was input. That's great except when you wrap it with f2py and have intent out, f2py needs to guess what length string to allocate and pass to your function and it has no way of doing that. (After all, what length string should it assume?).

It looks to me like f2py assumes a 0 length string. When you assign a bigger string to a smaller string in fortran, the result gets truncated (although I would need to go back and read the standard to find out if that could result memory errors). In any event, it looks like that's what the gnu compiler is doing.

If you change it to len=3, it works.

Alternatively, doing something like this can make this work for f2py without modifying the original code (except for some comments):

      !f2py character(len=256),intent(out):: chid
      character(len=*),intent(out):: chid          ! char. identifier
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you! You're absolutely right. Do you know if I can tell f2py to assume something else? I'd rather not go in and modify me legacy code unless it's really necessary...
@Paul -- I doubt it. You could try to use f2py to generate a signature file and then edit that (although I've never bothered to do anything like that ...). you also might be able to do a little magic with intent(inout), although I'm not sure how that would go with python strings since they're immutable ...
Found the answer to that question. If I add this line above the declaration !f2py character(len=256),intent(out):: chid it works! It looks better if I strip the string of whitespace in Python test.foo().strip()
@Paul -- O, that's true. Sorry, I thought you were trying to avoid touching the original source, otherwise I might have tried to advocate something like that.:).
Fair point. I think I can live with some extra comments ;) I'll add this possibility to your answer btw
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.