Fortran 如何使作为参数传递的子例程名称在整个模块中可用?
我希望使用一个变量子例程名称,并且我希望这个名称在整个模块中都可用,而不仅仅是在单个子例程中 作为参数传递的变量子例程名称是一种数据类型。它存放在哪里?我如何访问它 这里有更多的解释。G是一个非线性拟合程序。H使用G,但参数分组(迭代一次移动一个组)。G使用一个通用的正向模型子例程,其名称作为参数传递。我希望H保留这种普遍性 以下是使用带有硬编码子例程名称的变通方法的测试程序:Fortran 如何使作为参数传递的子例程名称在整个模块中可用?,fortran,arguments,subroutine,fortran95,Fortran,Arguments,Subroutine,Fortran95,我希望使用一个变量子例程名称,并且我希望这个名称在整个模块中都可用,而不仅仅是在单个子例程中 作为参数传递的变量子例程名称是一种数据类型。它存放在哪里?我如何访问它 这里有更多的解释。G是一个非线性拟合程序。H使用G,但参数分组(迭代一次移动一个组)。G使用一个通用的正向模型子例程,其名称作为参数传递。我希望H保留这种普遍性 以下是使用带有硬编码子例程名称的变通方法的测试程序: module G_MOD implicit none character(len=30)::message
module G_MOD
implicit none
character(len=30)::message='Good Morning'
contains
subroutine G(Sub)
external::Sub
call Sub
end subroutine G
end module G_MOD
module H_MOD
use G_MOD
implicit none
contains
subroutine H(sub)
external:: sub
call G(LocalSub)
end subroutine H
subroutine LocalSub
external:: MySub
message='Good Afternoon'
call G(MySub) ! the subroutine name "MySub" is hardcoded
! I would like it to be argument sub
end subroutine LocalSub
end module H_MOD
program test
use H_MOD
implicit none
external MySub
call H(MySub)
end program test
subroutine MySub
use G_MOD,only:message
write(*,*)trim(Message)
end subroutine MySub
解决方案1
如果将LocalSub
设置为H
内部,则无需存储任何内容:
subroutine H(sub)
external:: sub
call G(LocalSub)
contains
subroutine LocalSub
message='Good Afternoon'
call G(sub)
end subroutine LocalSub
end subroutine H
它需要Fortran 2008
通过一些清理、缩进以提高可读性、使用抽象接口删除丑陋的外部(Fortran 2003,但即使在使用接口块的Fortran 90中也可以避免external
),代码是:
module G_MOD
implicit none
character(len=30)::message='Good Morning'
abstract interface
subroutine sub_interface
end subroutine
end interface
contains
subroutine G(Sub)
procedure(sub_interface) :: sub
call Sub
end subroutine G
end module G_MOD
module H_MOD
use G_MOD
implicit none
contains
subroutine H(sub)
procedure(sub_interface) :: sub
call G(LocalSub)
contains
subroutine LocalSub
message='Good Afternoon'
call G(sub)
end subroutine LocalSub
end subroutine H
end module H_MOD
program test
use H_MOD
implicit none
call H(MySub)
contains
subroutine MySub
use G_MOD,only:message
write(*,*)trim(Message)
end subroutine MySub
end program test
解决方案2 如果您确实想在模块中存储对过程的引用,这是可能的,但请记住全局变量很难看。如果您想并行调用多个优化,该怎么办 因此,您可以将过程的地址(而不是名称)存储在
过程指针中。这些都需要Fortran 2003。对代码的最小更改是
module H_MOD
use G_MOD
implicit none
procedure, pointer :: stored_sub => null()
contains
subroutine H(sub)
external:: sub
stored_sub => sub
call G(LocalSub)
end subroutine H
subroutine LocalSub
message='Good Afternoon'
call G(stored_sub)
end subroutine LocalSub
end module H_MOD
但更好的现代代码是:
module G_MOD
implicit none
character(len=30)::message='Good Morning'
abstract interface
subroutine sub_interface
end subroutine
end interface
contains
subroutine G(Sub)
procedure(sub_interface) :: sub
call Sub
end subroutine G
end module G_MOD
module H_MOD
use G_MOD
implicit none
procedure(sub_interface), pointer :: stored_sub => null()
contains
subroutine H(sub)
procedure(sub_interface) :: sub
stored_sub => sub
call G(LocalSub)
end subroutine H
subroutine LocalSub
message='Good Afternoon'
call G(stored_sub)
end subroutine LocalSub
end module H_MOD
module MySub_module
contains
subroutine MySub
use G_MOD,only:message
write(*,*)trim(Message)
end subroutine MySub
end module MySub_module
program test
use H_MOD
use MySub_module
implicit none
call H(MySub)
end program test
尽管如此,我还是更喜欢带有内部程序的变体
请记住,使用缩进,这对于可读代码至关重要。对所有Fortran问题使用标记以引起更多注意。当您有模块时,不要使用外部标记。在Fortran 2003中有一些很好的方法。出于某种原因,您是否需要严格的旧Fortran 95?如果您修改它,可能会发生重复情况?修改的问题是在行调用G(存储的\u sub)之前添加行调用存储的\u sub。这应该功能相同,并产生两条“午安”消息。但是,它会导致G95的编译失败,而不会导致Intel(在文件解决方案2中)的编译失败。例如:36调用存储的\u sub 1错误:位于(1)的符号“存储的\u sub”没有隐式类型。G95中存在一些错误。忘记G95,它是旧的,不再受支持。请改用gfortran。