如何使用inteface块将函数传递给子例程? [英] How to use inteface blocks to pass a function to a subroutine?

查看:190
本文介绍了如何使用inteface块将函数传递给子例程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我明白接口命令可以用来将一个函数传递给一个子例程。因此,例如在主程序中,我会定义一些函数,然后将其传递给一些子例程:

  MainProgran 

使用....

隐含无

类型装饰等

接口
函数test(x,y )
实数,INTENT(IN):: x,y
REAL :: test
END函数
结束接口

调用子程序(limit1,limit2 ,test,Ans)


结束MainProgram

这是这样做的正确方法?我很困难!同样在子例程中,有什么我需要让它知道一个函数正在进入?在这种情况下,子例程将是一个库,所以我不想不得不重新编译它来改变函数。

解决方案

我现在知道的最优雅的方式是将你的函数放入一个模块中,这样你就不必做构建接口,但只需使用'外部'。这是一个例子。

它包含使用子程序或函数作为子程序或函数的参数的不同情况。



注意,如果你想传递数组作为参数而不接收null arraies,这里是一个提示。



模块部分:

  module func_arg_test 
!我用ifort编译,但其他编译器也应该没问题。
!由Kee
!撰写2017年2月20日
包含

!------------------- ------
真实函数func_func(f,arg)
!=========================== =============
!这显示了如何将参数传递给
!=================== =====================
implicit none
real,external :: f!使用external来表示f是函数的名称
real :: arg

func_func = f(arg)
结束函数func_func

实函数func_sub(subr,arg)
! ========================================
!这显示了如何通过子程序作为参数运行
!========================================
implicit none
external :: subr!使用external来指示subr是一个子例程
real :: arg

调用子(arg)
func_sub = arg
结束函数func_sub


子程序sub_func(f,arg)
!================== ======================
!这显示了如何在子程序
!中传递函数作为参数
!=== ================== ===================
real :: arg
real,external :: f
arg = f(arg)
结束子程序sub_func

子程序sub_sub(subr,arg)
!========================== ==============
!这显示了如何在子程序
中传递子程序作为参数
!=========== =============================
real :: arg
external :: subr
call subr(arg)
end subroutine sub_sub




实函数funcmat(f,mat)
!====== ==================================
!这显示了如何传递矩阵作为参数
!========================================
implicit none
real,external :: f
real,dimension(:) :: mat!当mat为
!时,mat已经被分配了,所以不需要特定的大小
integer :: sizeinfo
sizeinfo = size(mat)
funcmat = f(mat,sizeinfo)
结束函数funcmat
!----------- ---------------

实函数f1(arg)
!这个测试函数加倍数字arg
implicit no ne
real :: arg
f1 = arg * 2
返回
结束函数f1

实函数f2(arg)
!测试函数平方数arg
隐式无
real :: arg
f2 = arg * arg
返回
结束函数f2

real函数fmat(mat,sizeinfo)
!这个测试函数总结了mat
中的所有元素implicit none
integer :: sizeinfo!这是我想出的方法来解决
!限制。
real,dimension(sizeinfo):: mat!这个垫子不能确定,否则
!将不能正确接收。我不知道为什么。
fmat = sum(mat)
结束函数fmat

子程序sub(arg)
real :: arg
arg = arg * 3
结束子程序sub
结束模块

主程序:

 程序主体
使用func_arg_test
隐式无
真正:: a = 5d0
真实::输出
real,dimension(:),allocatable :: mat

写入(*,*)'a ='的值,a
输出= func_func(f1,a)
* write(*,*)'a doubled'
write(*,*)output
output = func_func(f2,a)
write(*,*)'a is squared'
写(*,*)输出
输出= func_sub(sub,a)
写(*,*)'a被三倍并覆盖'
write(*,*)输出
调用sub_func(f2,a)
write(*,*)'a被平方并覆盖'
write(*,*)a
调用sub_sub(sub,a )
write(*,*)'a被三倍并被覆盖'
write(*,*)a

allocate(mat(3))
mat = (/ 1d0,10d0,1d0 /)!可分配的arrray必须在
!传递为arg之前具有确定的形状uemnt
write(*,*)'1D matrix:',mat
write(*,*)'矩阵求和:'
output = funcmat(fmat,mat)! (*,*)输出

结束程序



结果是:

  a = 5.000000 
a的值加倍
10.00000
a平方
25.00000
a翻三倍并被覆盖
15.00000
a被平方并被覆盖
225.0000
a翻三倍并被覆盖
675.0000
1D矩阵:1.000000 10.00000 1.000000
矩阵求和:
12.00000


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 subroutine like:

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

Is this the correct way of doing this? I'm quite stuck! Also within the Subroutine is there anything I need to put to let it know that a function is coming in? The Subroutine in this case will be a library so I don't want to have to keep recompiling it to change the function.

解决方案

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.

It covers different situations using subroutine or function as arguments for subroutine or function.

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    

这篇关于如何使用inteface块将函数传递给子例程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆