0

Consider the code:

subroutine func(i) bind(c)
  use, intrinsic :: ISO_C_BINDING, only: c_float
  implicit none
  real(c_float), value :: i
  print *, i, "+", i, "=", i + i
end subroutine

program main
  use, intrinsic :: ISO_C_BINDING, only: c_float
  implicit none
  real(c_float) :: i = 1.0
  call func(i)
end program

It displays 5.61379690E-30 + 5.61379690E-30 = 1.12275938E-29, which is of course wrong. Only if I add an explicit interface, it outputs the correct results:

subroutine func(i) bind(c)
  use, intrinsic :: ISO_C_BINDING, only: c_float
  implicit none
  real(c_float), value :: i
  print *, i, "+", i, "=", i + i
end subroutine

program main
  implicit none
  interface
    subroutine func(i)
      real, value :: i
    end subroutine func
  end interface
  real :: i = 1.0
  call func(i)
end program

I then get 1.00000000 + 1.00000000 = 2.00000000 which is correct.

But what is causing the error here? Why is an extra interface required that doesn't add any new information?

I use gfortran, GCC, Version 7.4.0

1 Answers1

0

Every function or subroutine that has value dummy argument requires an explicit interface. The same holds for procedures that have the bind() attribute. Otherwise the calling code does not know how to call it properly.

The Fortran 2018 draft states:

15.4.2.2 Explicit interface
1 Within the scope of a procedure identifier, the procedure shall have an explicit interface if it is not a statement function and
...
(3) the procedure has a dummy argument that (a) has the ALLOCATABLE, ASYNCHRONOUS, OPTIONAL, POINTER, TARGET, VALUE, or VOLATILE attribute, ...
...
(6) the procedure has the BIND attribute.

Note that an explicit interface is not the same as the interface block you used. The interface block is one of the possible ways how to provide the explicit interface. A better alternative is often to use a module and sometimes to use an internal procedure.

The standard defines explicit interface as:

3.90.2
explicit interface
interface of a procedure that includes all the characteristics of the procedure and names for its dummy arguments except for asterisk dummy arguments (15.4.2)

That is different form an interface block, that is an actual piece of code that starts with the interface keyword.

  • Ok this is good to know, thank you. But why is the interface not an explicit? I got the syntax from [this](https://w3.pppl.gov/~hammett/comp/f90tut/f90.tut4.html) tutorial (section interface blocks) which refered to it as 'explicit' (but didn't mention it is required for value arguments, only optional, keyword, pointer, etc.)... How can I change the interface in the question so that it is really explicit and correct? – user3137490 Sep 26 '20 at 10:45
  • @user3137490 Your interface block in the second sample DOES provide an explicit interface. In your first code sample the function is external so the interface is implicit. – Vladimir F Героям слава Sep 26 '20 at 10:48
  • @user3137490 Please read https://stackoverflow.com/questions/16486822/fortran-explicit-interface – Vladimir F Героям слава Sep 26 '20 at 10:49
  • 1
    Just stick all your subroutines and functions in modules, then you will never have to worry about this, and gain other advantages as well. – Ian Bush Sep 26 '20 at 11:40