使用 Fortran 模块以菊花链方式连接 USE 语句



我问题的上下文并不容易描述,所以只要说我有充分的理由尝试构建一个DLL F90项目就足够了 -

  • 我有一些低级模块(特点是很少或没有 对其他模块的依赖(,
  • 一些中级模块(即 主要使用来自低级别的数据执行中间计算 模块(和
  • 一些高级模块(和主 DLL( 将这些计算的结果组合到输出中。

我的目标结构的简化版本最终会得到这样的结果:

  • 模块 1(无依赖项(
  • 模块 2(无依赖项(
  • 模块 3(USE 模块 1(
  • 模块 4(USE 模块 2(
  • 模块 5(USE 模块 1 参数和模块 3 方法(
  • 模块 6(USE 模块 2 参数和模块 4 方法(
  • 主 DLL 代码(使用上述所有模块(

问题:

我是否需要在主 DLL 代码中显式使用所有模块,还是只需使用 module5 和 module6 即可继承"最低"级别的变量和方法?

或者,模块 5 需要两个 USE 语句(模块 1 和模块 3(还是只需要模块 3?

而且,我还想在我的主 DLL 代码(例如 pi(中访问一些全局常量,例如 module1,所以我需要 module1 公共变量位于全局命名空间中。

我是否需要在主 DLL 代码中显式使用所有模块, 还是将继承"最低"级别的变量和方法 简单地使用模块 5 和模块 6?

如果该实体在使用的模块中公开,则不需要将模块一直使用到依赖项来访问该实体。

或者,模块 5 需要两个 USE 语句(模块 1 和模块 3(还是只需要模块 3?

只需使用module5您就可以访问:

  • module5本身中声明的任何模块实体,标记为publicprotected
  • module5中由USE关联访问的任何实体,被module5标记为public(实际上,如果没有指定任何内容,则公共是默认的可访问性(。如果一个实体通过 USE 关联从module1module3访问,但被module5标记为private,则无法访问该实体。

我试图在下面的示例中涵盖尽可能多的情况。我只使用变量声明,但同样适用于变量、过程、用户定义的类型、运算符、接口......

module module0
! Utiliy module with global constants, could be used at any level.
character(2) :: w = 'w0'
end
module module1
! Low level module. Exposes all the symbols that are not marked as private,
! both defined locally or accessed by use from 'module0'.
use :: module0
private :: z
character(2) :: x1 = 'x1', y1 = 'y1', z = 'z1'
! defined entities: w, x1, y1, z 
! public entities : w, x1, y1
end
module module2
! Also low level module, but default access modifier was changed to private,
! so it exposes only symbols marked as public ('z' isn't).
use :: module0
public :: w, x2, y2
private
character(2) :: x2 = 'x2', y2 = 'y2', z = 'z2'
! defined entities: w, x2, y2, z 
! public entities : w, x2, y2
end
module module3
! Uses all public names from 'module1' (including 'w' that is from 'module0'),
! but only exposes some of them. Also, defines and exposes local symbols.
use :: module1
private :: x3, y1
character(2) :: x3 = 'x3', y3 = 'y3'
! defined entities: w, x1, y1, x3, y3
! public entities : w, x1, y3
end
module module4
! Here, only selected symbols are accessed from 'module2', and 'w' has been
! renamed into 'w2' to avoid name-conflict with locally defined name 'w'
! (a compile error would had been thrown).
use :: module2, only: w2 => w, x2
public :: w, x2, y4
private
character(2) :: w = 'w4', x4 = 'x4', y4 = 'y4'
! defined entities: w, w2, x2, x4, y4
! public entities : w, x2, y4
end
module module5
! This module can use symbols from lowest level modules that are made public
! by 'module3', without explicitly using those modules.
use :: module3
character(2) :: z = 'z5'
! defined entities: w, x1, y3, z
! public entities : w, x1, y3, z
end
module module6
! As 'y2' is not exposed by 'module4', we could have access to it by using
! 'module2' directly. There is no name-conflict between 'w' from 'module0' 
! and from 'module2' because both relate to the same entity. There would be
! conflict with 'w' from 'module4' though, hence the rename.
use :: module0
use :: module2
use :: module4, w4 => w
public :: w, x2, y4, z
private
character(2) :: z = 'z6'
! defined entities: w, w4, x2, y2, y4, z
! public entities : w, x2, y4, z
end

我强烈建议您尽可能尝试使用显式导入,因为它使您的代码更加清晰并避免名称冲突。作为一般规则,尝试在模块中使用公共实体的离散名称,或在 USE 语句中使用重命名子句。

这是前面模块的用法示例:

program main
! There aren't namespaces in Fortran (yet), so attention shall be paid when
! naming symbols meant to be accessed by use association, to avoid conflicts.
! That's why explicit imports are encouraged, as well as implicit none.
use :: module5
use :: module6, z6 => z
implicit none      
character(2) :: v = 'v#'
call test_a
call test_b
call test_c
contains
subroutine test_a
! You can access used and defined names in procedures by host association.
print '(5a3)', v, w, x1, y3, z   ! output: v# w0 x1 y3 z5
print '(5a3)', v, w, x2, y4, z6  ! output: v# w0 x2 y4 z6
end
subroutine test_b
! Also, you can use modules locally inside procedures. In this case, local
! names "shadow" host associated names, as with 'z' from 'module6' here.
use :: module6
print '(5a3)', v, w, x2, y4, z  ! output: v# w0 x2 y4 z6
end
subroutine test_c
! There is no name-conflict error between host and local symbols; the local
! definition (or use association) always "shadows" the host associated name.
use :: module4, only: w
character(2) :: v = 'v_', z = 'z_'
print '(5a3)', v, w, x1, y3, z   ! output: v_ w4 x1 y3 z_
end
end

为了完整起见,我要提一下,Fortran 2018标准包括一个名为"默认可访问性"的新功能,该功能适用于从模块访问的实体,该功能允许您将模块名称放在publicprivate语句中,将所述可访问性修饰符应用于该模块中所有使用的实体。

如果模块 a 使用模块 b,则实体的默认可访问性 来自 B 的访问是公共的。为每个指定另一个辅助功能 实体很笨拙且容易出错。现在可以命名 一个模块,将列入公开实体名称清单 或私人或私人声明。这将设置默认值 从该模块访问的所有实体。

我今天(2018 年(知道的唯一包含此功能的编译器是 Intel Visual Fortran 19.0。

相关内容

最新更新