Как указать переменную модуля как часть объявления фиктивного аргумента внутри интерфейсного блока? - PullRequest
1 голос
/ 13 июля 2020

У меня есть подпрограмма 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_x, file_x.f90 с помощью ifort -c file_x.f90, я получил сообщение об ошибке: «IMPORT-name должно быть именем объекта в блоке области видимости хоста. [M]», показывая, что компилятор не был в состоянии разрешить m. Возможно, он сможет разрешить c_long и c_double из-за наличия use, intrinsic :: iso_c_binding в определении mod_x, но я могу ошибаться. Добавление use mod_a, only : m в определение mod_x может решить проблему, но это означает, что mod_x будет зависеть от mod_a, и я стараюсь избегать зависимости между модулями.

Один из способов, который кажется работающим, - это перемещение блок интерфейса в обычный текстовый файл, скажем interface_x.f90, и добавьте строку include "interface_x.f90" в любую процедуру, вызывающую sub_x. Но я стараюсь избегать использования этого метода, потому что у меня есть десятки внешних подпрограмм, и лучше иметь интерфейсы всех из них в одном файле. Если бы я использовал это, почти любая процедура, имеющая include "interface_x.f90", должна была бы иметь use mod_a, only : m, даже если она не требует m. Какое решение?

1 Ответ

2 голосов
/ 13 июля 2020

Нет необходимости использовать оператор import, чтобы сделать объект доступным в блоке интерфейса. Это один способ, а в некоторых случаях и единственный. Это не один из тех случаев.

Оператор import управляет доступностью сущностей из области хоста блока области видимости (например, блока интерфейса). В (упрощенном) случае вопроса

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

оператор импорта делает объект c_long из области видимости модуля доступным в спецификации интерфейса sub_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

(Или, что то же самое, путем объединения import с use mod_a в области видимости модуля.)

Обратите внимание, что это зависимость модуля, как бы вы ее ни записали: mod_x зависит от mod_a, потому что интерфейс, указанный в mod_x, имеет характеристики c, определяемые сущностью в mod_a.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...