在Fortran中正确使用模块,子例程和函数
我最近在向我的FORTRAN
程序添加函数时了解了interface block
。 一切工作很好,整齐,但现在我想添加第二个function到interface block
。
这是我的接口块:
interface function correctNeighLabel (A,i,j,k) integer :: correctNeighLabel integer, intent(in) :: i,j,k integer,dimension(:,:,:),intent(inout) :: A end function function correctNeighArray (B,d,e,f) character :: correctNeighArray integer, intent(in) :: d,e,f character, dimension(:,:,:),intent(inout) :: B end function end interface
在我看来,这可能不是最好的select。
我已经研究过子程序,但我不是很确信这是正确的解决scheme。 我所做的是相对简单的,我需要将parameter passing给子例程,但是我所看到的所有子例程都是复杂的(即对于函数来说太复杂),并且b)不采取参数performance得像操纵variables而不传递给它们。
我没有真正地查看模块,但从我所看到的是不正确的使用。
任何build议什么时候使用,以及如何去做最好的将非常感激。
模块总是正确的使用;-)
如果你有一个非常简单的F90程序,你可以在'contains'块中包含函数和子程序:
program simple implicit none integer :: x, y x = ... y = myfunc(x) contains function myfunc(x) result(y) implicit none integer, intent(in) :: x integer :: y ... end function myfunc end program
那么函数/子程序的接口在程序中是已知的,不需要在接口块中定义。
对于更复杂的程序,您应该将所有的function/子程序保存在模块中,并在需要时加载它们。 所以你不需要定义接口,
module mymod implicit none private public :: myfunc contains function myfunc(x) result(y) implicit none integer, intent(in) :: x integer :: y ... end function myfunc end module mymod program advanced use mymod, only: myfunc implicit none integer :: x, y x = ... y = myfunc(x) end program advanced
模块和程序可以(实际上应该)在单独的文件中,但是模块必须在实际程序之前被编译。
借用和延伸已经说过的话。 把你的程序(子程序和函数)放到模块中并“使用”它们会更好,因为它们可以很轻松地实现接口的自动一致性检查。 其他方式有缺点。 如果使用接口块定义接口,则有三件事情要维护,而不是两件事:接口,过程本身和调用。 如果你做了改变,那么所有三个都必须修改,以保持一致。 如果您使用模块,则只能更改两个模块。 使用接口块的原因是,如果您无法访问源代码(例如,预编译的库)或者源代码是使用其他语言(例如,您正在通过ISO C绑定使用C代码)。
“包含”方法的缺点是包含的程序inheritance了父程序的所有局部variables……这是不是很模块化,如果你忘记了这个“特征”,可能会非常混乱。
alexurba和MSB的答案像往常一样正确和有用; 让我在一点上稍微详细一点 – 如果模块是要走的路(它们是),那么接口是什么?
对于模块中的函数和子例程,任何use
该模块的东西都可以自动查看这些接口; 接口是在编译模块时生成的(除了别的以外,这些信息进入了编译模块时生成的.mod文件)。 所以你不需要自己写。 同样,当你使用一个CONTAIN
ed子程序(与MSB同意,我发现更多的困惑,然后有用的 – 他们更好地被认为是封闭或嵌套子程序比外部子程序),主程序已经可以“看到”接口明确,并不需要你写出来。
当你无法做到这一点的时候,接口块是用于编译器不能为你生成显式接口,或者当你想要的东西与给定的不同的时候。 一个例子是在Fortran 2003中使用C-Fortran互操作性 。在这种情况下,Fortran代码与某个C库链接(比如说),并且无法为您生成一个正确的Fortran接口到C例程 – 您必须自己做,通过编写自己的接口块。
另一个例子是,当你已经知道子程序的接口,但是当你想创build一个新的接口来“隐藏”子程序 – 例如,当你有一个例程运行(比如说)整数,一个例子,并且您希望能够调用相同的例程名称,并让编译器根据参数对其进行sorting。 这样的结构被称为generics例程,并且自从Fortran 90以来就一直存在。在这种情况下,您将明确创build一个接口到这个新的generics例程,并将接口列入该接口块中的“真实”例程。