I understand the interface command can be used to pass a a function into a subroutine. So for example in the main program I\'d define some function and then pass it to some subr
The most elegant way I know of right now is to put your functions into a module so that you don't have to do construct interface but simply use 'external'. Here is a example to do that.
Notice if you want to pass array as argument without receiving null arraies, here is a tip to do that.
Module part:
module func_arg_test
!I used ifort to compile but other compilers should also be fine.
!Written by Kee
!Feb 20, 2017
contains
!-------------------------
real function func_func(f, arg)
!========================================
!This shows how to pass number as argument
!========================================
implicit none
real, external::f !Use external to indicate the f is a name of a function
real::arg
func_func=f(arg)
end function func_func
real function func_sub(subr, arg)
!========================================
!This shows how to pass subroutine as arg to function
!========================================
implicit none
external::subr !Use external to indicate subr is a subroutine
real::arg
call sub(arg)
func_sub = arg
end function func_sub
subroutine sub_func(f,arg)
!========================================
!This shows how to pass function as argument
!in subroutine 
!========================================
real::arg
real,external::f
arg = f(arg)
end subroutine sub_func
subroutine sub_sub(subr,arg)
!========================================
!This shows how to pass subroutine as argument
!in subroutine 
!========================================
real::arg
external::subr
call subr(arg)
end subroutine sub_sub
real function funcmat(f, mat)
!========================================
!This shows how to pass matrix as argument
!========================================
implicit none
real, external::f
real,dimension(:)::mat!Here memory for mat is already allocated when mat is
!passed in, so don't need specific size
integer::sizeinfo
sizeinfo = size(mat)
funcmat = f(mat,sizeinfo)
end function funcmat
!--------------------------
real function f1(arg)
!This test function double the number arg
implicit none
real::arg
f1 = arg*2
return
end function f1
real function f2(arg)
!This test function square the number arg
implicit none
real::arg
f2 = arg*arg
return
end function f2
real function fmat(mat,sizeinfo)
!This test function sum up all elements in the mat
implicit none
integer::sizeinfo!This is the method I come up with to get around the
!restriction.
real,dimension(sizeinfo)::mat!This mat cannot be undetermined, otherwise it
!won't recevie mat correctly. I don't know why yet.
fmat = sum(mat)
end function fmat
subroutine sub(arg)
real::arg
arg = arg*3
end subroutine sub
end module
Main program:
program main
use func_arg_test
implicit none
real::a = 5d0
real::output
real, dimension(:),allocatable::mat
write(*,*) 'value of a=',a
output = func_func(f1,a)
write(*,*) 'a is  doubled'
write(*,*) output
output = func_func(f2,a)
write(*,*) 'a is squared'
write(*,*) output
output = func_sub(sub,a)
write(*,*) 'a is tripled and overwritten'
write(*,*) output
call sub_func(f2,a)
write(*,*) 'a is squared and overwritten'
write(*,*) a
call sub_sub(sub,a)
write(*,*) 'a is tripled and overwritten'
write(*,*) a
allocate(mat(3))
mat = (/1d0,10d0,1d0/)!The allocatable arrray has to have a determined shape before
!pass as arguemnt
write(*,*) '1D matrix:',mat
write(*,*) 'Summation of the matrix:'
output = funcmat(fmat,mat)!elements of mat are summed
write(*,*) output
end program
And the result is:
value of a=   5.000000    
 a is  doubled
   10.00000    
 a is squared
   25.00000    
 a is tripled and overwritten
   15.00000    
 a is squared and overwritten
   225.0000    
 a is tripled and overwritten
   675.0000    
 1D matrix:   1.000000       10.00000       1.000000    
 Summation of the matrix:
   12.00000    
 
                                                                        A simple way to do this is to go old school and just leave the function external:
 program main
 real f,z
 external f
 call subr(f,z)
 write(*,*)z
 end
 real function f(x)
 real x
 f=x**2
 end
! below possibly in a precompiled library:
 subroutine subr(f,y)
 real f,y
 y=f(2.)
 end
out: 4
Of course with this approach you can not use advanced language features that require an explicit interface. **
On the other hand if you are interfacing with standard libraries that need function arguments this is I think the only way.
** per MSB's comment you can handle that issue with an interface block in the subroutine, for example if we want to pass a function that returns an array:
 function f(x)
 real x,f(2)
 f(1)=x
 f(2)=x**2
 end
as in the first example f is an external function, and the sub can be in a precompiled library:
 subroutine subr(g,y)
 interface
 function g(x)
 real x,g(2)
 end function
 end interface
 real y,z(2)
 z=g(2.)
 y=z(1)+z(2)
 end
out: 6
As noted, this is only strictly necessary if relying on language features that need the interface.
Module:
module fmod
    interface
       function f_interf(x,y)
       real, intent(in) :: x, y
       real :: f_interf
       end function
    end interface
contains 
    function f_sum(x,y)
    real, intent(in) :: x, y
    real f_sum
    f_sum = x + y
    end function
    function f_subst(x,y)
    real, intent(in) :: x, y
    real f_subst
    f_subst = x - y
    end function
    subroutine subr(limit1, limit2, func, ans)
    real limit1, limit2
    procedure(f_interf) func
    real ans
    ans = func(limit1, limit2)
    end subroutine
end module
main program:
program pass_func
use fmod
Implicit None
real ans, limit1, limit2
limit1 = 1.0
limit2 = 2.0
call subr( limit1, limit2, f_subst, ans)
write(*,*) ans
call subr( limit1, limit2, f_sum, ans)
write(*,*) ans
end program pass_func
and output:
  -1.000000
   3.000000