0

I have the following Fortran source code intended to be compiled with f2py to be used by Numpy/Python.

subroutine get_value(ts, c_open)

        implicit none

        ! INPUT PARAMETERS 
        integer(kind=4), intent(in)                :: ts(:)                

        ! OUTPUT PARAMETERS             
        integer(kind=4), intent(out)               :: c_open               

        ! SIMULATED CALCULATION
        c_open = ts(1)
        
end subroutine

subroutine get_value_range(ts, a, b, c_open)

        implicit none

        ! INPUT PARAMETERS         
        integer(kind=4), intent(in)                :: ts(:)
        integer(kind=4), intent(in)                :: a
        integer(kind=4), intent(in)                :: b         

        ! OUTPUT PARAMETERS              
        ! - AGGREGATED VALUES TO RETURN
        integer(kind=4), intent(out)               :: c_open(b-a)

        ! INDIVIDUAL RETURN VALUES
        integer(kind=4)                            :: c1_open

        ! AUXILIARY VARIABLES
        integer                                    :: i                    ! ITERATOR
        
        ! FILL IN OUTPUT ARRAY
        do i = 1,10
                call get_value( ts, c1_open)
                c_open(i) = c1_open
        end do
                

end subroutine

Basically get_value calculates a value (in this example it just returns the value of the first item of the passed vector ts and get_value_range returns a vector of results using get_value function.

When I compile with f2py I get:

   37 |                 call get_value( ts, c1_open)
      |                              1
Error: Explicit interface required for 'get_value' at (1): assumed-shape argument

Why is this error being drop by f2py and is there any way to fix it?


EDIT:

I have been redirected here: Fortran - explicit interface and here: Procedure with assumed-shape dummy argument must have an explicit interface

Now if I understood those posts correctly the compiler requires to know the parameters of get_value in get_value_range. That can be done either encapsulating everything in a module or by using an internal procedure or by defining explicitly an interface.

I am still pretty new to f2py and I am not sure if in f2py you have to encapsulate everything in modules or just write the subroutines as stand alone subroutines in the file. So far I am following the later approach as by doing that I see that they are properly exposed to Python.

Assuming that I want to try the approach of an explicit interface I try this:

subroutine get_value(ts, c_open)

        implicit none

        ! INPUT PARAMETERS 
        integer(kind=4), intent(in)                :: ts(:)                

        ! OUTPUT PARAMETERS             
        integer(kind=4), intent(out)               :: c_open               

        ! SIMULATED CALCULATION
        c_open = ts(1)
        
end subroutine

subroutine get_value_range(ts, a, b, ca_open)

        implicit none
        
        ! INPUT PARAMETERS         
        integer(kind=4), intent(in)                :: ts(:)
        integer(kind=4), intent(in)                :: a
        integer(kind=4), intent(in)                :: b         

        ! OUTPUT PARAMETERS              
        ! - AGGREGATED VALUES TO RETURN
        integer(kind=4), intent(out)               :: ca_open(b-a)

        ! INDIVIDUAL RETURN VALUES
        integer(kind=4)                            :: c1_open

        ! AUXILIARY VARIABLES
        integer                                    :: i                    ! ITERATOR

        ! INTERFACE TO get_value
        interface
                function get_value(ts, c_open)
                        integer(kind=4), intent(in)                :: ts(:)                
                        integer(kind=4), intent(out)               :: c_open
                end function
        end interface
        
        ! FILL IN OUTPUT ARRAY
        do i = 1,10
                call get_value(ts, c1_open)
                ca_open(i) = c1_open
        end do
                

end subroutine

But then I get the following error:

   37 |                 function get_value(ts, c_open)
      |                1
......
   45 |                 call get_value(ts, c1_open)
      |                                           2
Error: 'get_value' at (1) has a type, which is not consistent with the CALL at (2)

So it seems that the compiler is now finding the definition of get_value but for some reason that I can not understand it is detecting an inconsistency between the function definition and the call.

EDIT 2:

There is a clear error in the definition as pointed out in the comments, the interface block defines a function instead of a subroutine.

However, when I modify it I get a new error:

subroutine get_value(ts, c_open)

        implicit none

        ! INPUT PARAMETERS 
        integer(kind=4), intent(in)                :: ts(:)                

        ! OUTPUT PARAMETERS             
        integer(kind=4), intent(out)               :: c_open               

        ! SIMULATED CALCULATION
        c_open = ts(1)
        
end subroutine

subroutine get_value_range(ts, a, b, ca_open)

        implicit none

        ! INTERFACE TO get_value
        interface
                subroutine get_value (ts, c_open)
                        integer(kind=4), intent(in)                :: ts(:)                
                        integer(kind=4), intent(out)               :: c_open
                end subroutine get_value
        end interface       
        
        ! INPUT PARAMETERS         
        integer(kind=4), intent(in)                :: ts(:)
        integer(kind=4), intent(in)                :: a
        integer(kind=4), intent(in)                :: b         

        ! OUTPUT PARAMETERS              
        ! - AGGREGATED VALUES TO RETURN
        integer(kind=4), intent(out)               :: ca_open(b-a)

        ! INDIVIDUAL RETURN VALUES
        integer(kind=4)                            :: c1_open

        ! AUXILIARY VARIABLES
        integer                                    :: i                    ! ITERATOR
        
        ! FILL IN OUTPUT ARRAY
        do i = 1,10
                call get_value(ts, c1_open)
                ca_open(i) = c1_open
        end do
                

end subroutine

These are the new errors after trying to compile it with f2py:

   86 |               subroutine get_value(ts,c_open) ! in :tape_lib:./ohl
      |                                              1
Error: Syntax error in SUBROUTINE statement at (1)

   88 |                   integer(kind=4), intent(in),dimension(:) :: ts
      |                                                                        1
Error: Unexpected data declaration statement in INTERFACE block at (1)

   89 |                   integer(kind=4), intent(out) :: c_open
      |                                                                        1
Error: Unexpected data declaration statement in INTERFACE block at (1)

   90 |               end subroutine get_value
      |                 1
Error: Expecting END INTERFACE statement at (1)
M.E.
  • 4,955
  • 4
  • 49
  • 128
  • 1
    You get the error because there isn't an explicit interface available for `get_value`. Why do you think there is one available? – francescalus Jul 03 '21 at 23:23
  • I have a very limited experience with Fortran. I will search for interfaces in Fortran, feel free to elaborate a bit more to make it easier how to find some documentation/info to define such explicit interface. – M.E. Jul 03 '21 at 23:29
  • 1
    If you aren't aware of the concept of explicit interfaces then the linked questions should be suitable. If you are aware of them, but don't understand why you don't have one in this case then we may need to point elsewhere. – francescalus Jul 03 '21 at 23:35
  • If I understood them correctly, as I am just adding a couple of subroutines the compiler will not make the interfaces aware among each others. I have added an explicit interface definition for `get_value` without success as now I get `Error: get_value at (1) has a type, which is not consistent with the CALL at (2)` – M.E. Jul 04 '21 at 06:44
  • @francescalus I have edited the question with the new error after coding the explicit interface, I can also make a separate question if needed or if somebody can provide a comment here that helps me to understand why this explicit interface is failing that would be welcomed. – M.E. Jul 04 '21 at 06:57
  • 1
    In the interface block you declare `get_value` to be a function, but use it as a subroutine (`call get_value`). – francescalus Jul 04 '21 at 09:01
  • @francescalus That is a pretty embarrassing mistake. When I fix it I get however another set of errors as included in the second edit section. – M.E. Jul 04 '21 at 11:02
  • I think the question is now not covered by the duplicates (likely due to the fact that I am using `f2py`) so I will ask a new question. – M.E. Jul 04 '21 at 11:43

0 Answers0