Uzai
Uzai

Reputation: 121

Are interface blocks ever required to compile Fortran?

I'm trying to teach myself Fortran, and have been messing around with linking multiple files together. Following examples, I have been writing programs in one file, functions in another, and using interface blocks in my main program to refer to the external function.

I was testing how much information was needed in the interface block and realised that I can remove it entirely.

My program:

    program test
        implicit none
        real :: x, y, func

        x = 3
        y = func(x)
        print *, y
    end program test

And the function file:

    function func(x)
        implicit none
        real :: x, func
        func = x**3
    end function func

I then compile it using gfortran -o test test.f90 func.f90 and the code works as expected. My question is, why do I not need to include an interface block in my program file? Is it simply a matter of good practice, or does defining func as a real variable serve as shorthand? I am on Windows, having installed gfortran through minGW.

As an aside/related question, if I instead use a subroutine:

    subroutine func(x,y)
        implicit none
        real :: x,y
        y = x**3
    end subroutine func

And change the line y = func(x) to call func(x,y) then the code will work fine without any interface block or declaration. Why is this?

Upvotes: 2

Views: 1242

Answers (3)

bbu
bbu

Reputation: 782

There are some cases where interface blocks are needed. For example if the called subroutine uses a pointer, allocatable or assumed shape arrays (this list is not complete, see the standard for more):

integer, pointer :: x(:,:)  ! pointer attribute
integer, allocatable :: x(:,:)  ! pointer attribute
integer :: a(:,:)           ! assumed shape array

The pointer/allocatable have the advantage that the called subroutine can allocate it for the calling function. Assumed shape arrays automatically transfer the dimensions to the called subroutine.

If you use any of this your program will crash without explicit interface. Easiest solution is like said in the other answer: use modules to have the interface automtically correct. We use a perl script automatically extracting interfaces to have interface check without rewriting the code to modules (and avoid long compile times until all compilers reliably support Fortran 2008 submodules...)

Upvotes: 0

francescalus
francescalus

Reputation: 32396

The declaration real :: func in the main program here declares func to be a function with (default) real result. This function has an interface in the main program as a result, so it is legitimate to reference that function with y = func(x).

The interface in this case is implicit. In this way, the main program knows exactly three things about func:

  • it is a function (with that name);
  • it has the external attribute;
  • it has real result.

The reference to the function is compatible with that knowledge. Further, how you reference the function matches precisely the properties of the function itself.

Equally, in the case of the subroutine, a call func(x,y) tells the main program exactly three things, again with the implicit interface:

  • it is a subroutine (with that name);
  • it has the external attribute;
  • it takes two real arguments.

Those three things again match the subroutine's definition, so things are fine.

Loosely, then, you don't need an interface block in these cases because the implicit interfaces are good enough.

There are times when an explicit interface is required and in most (nearly all) cases an explicit interface is better. As you can see in other questions and answers, there are usually better ways to provide an explicit interface than using an interface block.

Upvotes: 2

Pierre de Buyl
Pierre de Buyl

Reputation: 7293

Why do I not need to include an interface block in my program file?

Since Fortran 90, the recommended way to define reusable functions and subroutines is to use modules.

module func_m
contains
    function func(x)
        implicit none
        real :: x, func
        func = x**3
    end function func
end module func_m

Then write use func_m in the main program, before implicit none: gfortran -c func_m.f90, gfortran -c test.f90 and gfortran -o test test.o func_m.o.

When you use modules, the compiler will check the type of the arguments of the functions. You also do not need to declare real :: func as the declarations are taken from the module.

When you compile as a "simple" object file, the compiler will simply call whatever function is named func without verification, as long as such a function is given in an object file.

The interface block is a kind of "in between". In your case, you could add one in the program file. This would force you to follow that declaration in the program. But it will not prevent linking to wrong functions at link time: there is no guarantee that the interface is right. It is mostly useful if you need to call C or FORTRAN 77 code from someone else, for which you couldn't use modules.

And change the line y = func(x) to call func(x,y) then the code will work fine without any interface block or declaration. Why is this?

The interface issue is orthogonal to the function vs subroutine issue.

Upvotes: 1

Related Questions