如何将模块变量指定为接口块内的伪参数声明的一部分?

How do you specify a module variable as a part of dummy argument declaration inside an interface block?

我有一个子程序 sub_x 定义为

subroutine sub_x(n, a)
  use, intrinsic :: iso_c_binding
  use mod_a, only : m
  implicit none
  integer(c_long), intent(in) :: n
  real(c_double), intent(in) :: a(1:m)
  .
  .
  .
  rest of the codes
  .
  .

也就是说,sub_x 依赖模块变量 m 作为其数组参数的范围。现在,在一个单独的文件中,sub_x 的界面块如下

module mod_x
  use, intrinsic :: iso_c_binding
  
  interface
     subroutine sub_x(n, a)
       import :: c_long, c_double, m
       integer(c_long), intent(in) :: n
       real(c_double), intent(in) :: a(1:m)
     end
  end interface
end module mod_x

并且任何调用 sub_x 的过程都会有一个 use mod_x 语句。当尝试编译包含模块 mod_xfile_x.f90ifort -c file_x.f90 的文件时,我收到错误消息“IMPORT-name 必须是主机作用域单元中实体的名称。[m]”显示编译器无法解析 m。由于 mod_x 定义中存在 use, intrinsic :: iso_c_binding,它可能能够解析 c_longc_double,但我可能错了。在 mod_x 定义中添加 use mod_a, only : m 可能会解决问题,但这意味着 mod_x 将依赖于 mod_a 并且我尽量避免模块之间的依赖性。

一种似乎有效的方法是将接口块移动到一个纯文本文件,比如 interface_x.f90,并在任何调用 sub_x 的过程中添加一个 include "interface_x.f90" 行。但我尽量避免使用这种方法,因为我有数十个外部子程序,最好将所有这些子程序的接口放在一个文件中。如果我要使用它,几乎所有具有 include "interface_x.f90" 的过程都必须具有 use mod_a, only : m,即使它不需要 m。有什么解决办法?

没有必要使用 import 语句使实体在界面块中可访问。这是一种方式,在某些情况下是唯一的方式。这不是其中之一。

import 语句控制范围块(例如接口块)的主机范围内实体的可访问性。在问题的(简化)情况下

module mod_x
  use, intrinsic :: iso_c_binding
  
  interface
     subroutine sub_x()
       import :: c_long
     end
  end interface
end module mod_x

import 语句使模块范围内的实体 c_longsub_x 的接口规范中可访问。该实体本身在模块范围内可用,因为它与模块 iso_c_binding.

关联

在接口规范中可以访问完全相同的实体
module mod_x
  interface
     subroutine sub_x()
       use, intrinsic :: iso_c_binding, only : c_long
     end
  end interface
end module mod_x

这与 sub_x 的实际子例程规范非常相似。 m 可以用同样的方式访问:

module mod_x
  interface
     subroutine sub_x(n, a)
       use, intrinsic :: iso_c_binding, only : c_long, c_double
       use mod_a, only : m
       integer(c_long), intent(in) :: n
       real(c_double), intent(in) :: a(1:m)
     end
  end interface
end module mod_x

(或者等效地通过在模块范围内组合 importuse mod_a。)

请注意,无论您以何种方式编写,这都是一个模块依赖关系:mod_x 依赖于 mod_a,因为 mod_x 中指定的接口具有由 [=] 中的实体确定的特征23=].