Skip to content

f2py fails for functions returning character(len=len(input_string)) #3425

Closed

Description

@chatcannon

I've written simple toupper() and tolower() functions in Fortran that start like this:

pure function toupper(str)
  character(len=*) intent(in) :: str
  character(len=len(str)) :: toupper
  ...

When wrapping these with f2py, I get an error looking like this:

/tmp/tmpmrZ5Ra/src.linux-x86_64-2.7/RMCfunctionsmodule.c: In function ‘f2py_rout_RMCfunctions_mod_functions_toupper’:
/tmp/tmpmrZ5Ra/src.linux-x86_64-2.7/RMCfunctionsmodule.c:926:23: error: ‘str_Dims’ undeclared (first use in this function)

slen(toupper) = len(str);
                      ^

I guess the len(str) needs to be replaced by slen(str).

This problem occurs with both f2py-2.7 and f2py-3.3
It does not depend on the name of the variable str - I tried a couple of other names.

Activity

  1. chatcannon commented on Jun 12, 2013

    @chatcannon
    ContributorAuthor

    Sorry, I couldn't work out how to tag this with component: numpy.f2py

  2. chatcannon commented on Jun 12, 2013

    @chatcannon
    ContributorAuthor

    P.S. I'm running numpy version 1.7.1 on Gentoo GNU/Linux

  3. charris commented on Feb 23, 2014

    @charris
    Member

    @chatcannon I suspect this problem persists, but could you try with numpy 1.8 or current development?

  4. Goutte commented on Apr 7, 2021

    @Goutte

    I can confirm the issue is still here in numpy 1.20.
    Barring a fix (it's been 8 years), any tip on how to bypass this issue would be welcome!

  5. melissawm commented on May 13, 2021

    @melissawm
    Member

    Here's what I've managed to get so far:

    1. Wrapping the following:
      pure function test(str)
        character(len=*), intent(in) :: str
        character(len=len(str)) :: test
        integer :: i
    
        test(1:1) = 'A'
        do i = 2, len(str)
           test(i:i) = str(i:i)
        enddo
        
      end function test

    I get:

    /tmp/tmpdg8zrhbc/src.linux-x86_64-3.9/stringsmodule.c: In function 'f2py_rout_strings_strings_test':
    /tmp/tmpdg8zrhbc/src.linux-x86_64-3.9/stringsmodule.c:279:20: error: 'str_Dims' undeclared (first use in this function)
      279 |   slen(test) = len(str);
          |                    ^~~
    1. I tried using a subroutine, with the following signature file:
    python module strings ! in 
        interface  ! in :strings
            module strings ! in :strings:strings.f90
                subroutine test(str, a) ! in :strings:strings.f90:strings
                    character*(*) intent(in) :: str
                    character*len(str) intent(out) :: a
                end subroutine test
            end module strings
        end interface 
    end python module strings

    Running $ f2py -c strings.f90 strings.pyf compiles fine, but

    >>> import strings
    >>> print(strings.strings.test.__doc__)  # should return a as output, but returns
    test(str,a)
    
    Wrapper for ``test``.
    
    Parameters
    ----------
    str : input string(len=-1)
    a : input string(len=1)

    (note the incorrect intent for a)

    1. Changing strings.pyf to use character(len=slen(str)), intent(out) :: a runs fine and works.

    So the problem seems to be when using a function but not a subroutine.

    When inspecting the code, IIUC the problem comes from the fact that we need to use slen for the C function wrapper, but len for the fortran function wrapper (both generated by f2py).

    My question to @pearu is if we should require the use of the slen expression in the pyf file in this case, or try to fix this from f2py itself, considering the two separate cases of the fortran and C function wrappers.

  6. pearu commented on May 31, 2021

    @pearu
    Contributor

    My first reaction (without looking at code) is that f2py should be fixed by replacing len(..) call with slen(..) when len is used in the context of character len specification. Note that there are three kinds of length functions involved here: slen and len defined by f2py and to be used withing .pyf files, and len that is Fortran intrinsic. f2py len should be used in the context of arrays while f2py slen in the context of character types.

  7. added a commit that references this issue on Jul 3, 2021
  8. self-assigned this
    on Jul 3, 2021
  9. added a commit that references this issue on Apr 4, 2022
  10. added a commit that references this issue on Jun 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions