Последовательные операторы USE с модулями Fortran - PullRequest
0 голосов
/ 05 октября 2018

Контекст к моему вопросу описать нелегко, поэтому достаточно сказать, что у меня есть веские причины для попытки структурировать проект DLL F90 так, чтобы -

  • У меня был низкий уровеньодноуровневые модули (характеризующиеся малой зависимостью или отсутствием зависимости от других модулей),
  • некоторые модули промежуточного уровня (которые в основном выполняют промежуточные вычисления с использованием данных из низкоуровневых модулей) и
  • некоторые высокиеодноуровневые модули (и основная DLL), которые собирают результаты этих вычислений в выходные данные.

Упрощенная версия моей целевой структуры в конечном итоге будет выглядеть примерно так:

  • module1 (без зависимостей)
  • module2 (без зависимостей)
  • module3 (USEs module1)
  • module4 (USEs module2)
  • module5 (ИСПОЛЬЗУЕТ параметры module1 и методы module3)
  • module6 (ИСПОЛЬЗУЕТ параметры module2 и методы module4)
  • основной код DLL (ИСПОЛЬЗУЕТ все вышеперечисленные модули)

Вопрос:

Нужно ли явно использовать все модули в основном коде DLL, или переменные и методы с «самых низких» уровней будут наследоваться простоиспользуя module5 и module6?

Или, для module5 нужны два оператора USE (module1 AND module3) ИЛИ только для module3?

И я также хочу получить доступ к некоторым глобальным константам, например, в, module1 в моем основном коде DLL (например, pi), поэтому мне нужно, чтобы публичные переменные module1 находились в глобальном пространстве имен.

1 Ответ

0 голосов
/ 06 октября 2018

Нужно ли ИСПОЛЬЗОВАТЬ все модули явно в основном коде DLL, или будут наследоваться переменные и методы с «самых низких» уровней, просто используя module5 и module6?

Вам не нужно для ИСПОЛЬЗОВАНИЯ модулей на всем пути к зависимостям только для доступа к сущности , если эта сущность была сделана общедоступной в используемом модуле .

Или для модуля 5 нужны два оператора USE (модуль 1 И модуль 3) ИЛИ только для модуля 3?

Просто с помощью module5 вы можете получить доступ к:

  • Любая сущность модуля, объявленная внутри module5, помеченная как public или protected
  • Любая сущность, доступная ассоциацией USE в module5, помеченная public как module5 (на самом деле общедоступность - это доступность по умолчанию, если ничего не было указано).Если к объекту обращается ассоциация USE из module1 или module3, но помечен как private module5, он не будет доступен.

Я попытался охватить столькоситуации, как я мог понять в следующем примере.Я использовал только объявления переменных, но то же самое применимо к переменным, процедурам, пользовательским типам, операторам, интерфейсам ...

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 включает новую функцию с именем Доступность по умолчанию для сущностей, доступ к которым осуществляется из модуля , который позволяет установить модульимя в операторе public или private, применяющем указанный модификатор доступности ко всем используемым объектам из этого модуля.

Если модуль a использует модуль b, доступность по умолчанию для объектов, к которым он обращается из bявляется публичным.Указание другой доступности для каждого объекта неудобно и подвержено ошибкам.Теперь возможно, чтобы имя модуля было включено в список имен объектов, которые становятся публичными или частными в публичном или частном заявлении.Это устанавливает значение по умолчанию для всех сущностей, доступных из этого модуля.

Единственный известный мне сегодня компилятор (2018), который включает эту функцию, - Intel Visual Fortran 19.0 .

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