如何使用接口块将函数传递给子例程?

时间:2014-03-06 12:01:31

标签: pointers user-interface fortran

我理解interface命令可用于将函数传递给子例程。因此,例如在主程序中,我定义了一些函数,然后将其传递给某些子例程,如:

MainProgran

Use ....

Implicit None

Type decorations etc

Interface
   Function test(x,y)
   REAL, INTENT(IN) :: x, y
   REAL :: test
   END function
End Interface

   Call Subroutine( limit1, limit2, test, Ans)


End MainProgram

这是正确的做法吗?我卡住了!同样在Subroutine内还有什么我需要知道函数进来吗?在这种情况下,Subroutine将是一个库,因此我不想继续重新编译它以更改功能。

3 个答案:

答案 0 :(得分:0)

简单这样做的方法就是上学,只需将函数留在外部:

 program main
 real f,z
 external f
 call subr(f,z)
 write(*,*)z
 end

 real function f(x)
 real x
 f=x**2
 end

!下面可能在预编译库中:

 subroutine subr(f,y)
 real f,y
 y=f(2.)
 end
  

out:4

当然,使用此方法,您无法使用需要显式界面的高级语言功能。 **

另一方面,如果你正在与需要函数参数的标准库接口,那么我认为这是唯一的方法。

**根据MSB的评论,您可以在子程序中使用接口块处理该问题, 例如,如果我们想传递一个返回数组的函数:

 function f(x)
 real x,f(2)
 f(1)=x
 f(2)=x**2
 end

与第一个例子中一样,f是外部函数,sub可以是 预编译库:

 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

如上所述,如果依赖于需要界面的语言功能,这是非常必要的。

答案 1 :(得分:0)

模块:

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

主程序:

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

并输出:

  -1.000000
   3.000000

答案 2 :(得分:0)

我现在知道的最优雅的方法是将您的功能放入一个模块中,这样您就不必构建界面,只需使用“外部”即可。这是一个例子。

它使用子程序或函数作为子程序或函数的参数来涵盖不同的情况。

请注意,如果你想将数组作为参数传递而不接收空的arraies,这里有一个提示。

模块部分:

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

主程序:

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

结果是:

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