Fortran中使用子模块解决泛型赋值的模块相互依赖问题
可以通过Fortran的子模块(Submodules)解决该双向依赖导致的编译问题,具体说明如下:
原问题原因
原代码中MyType1Mod和MyType2Mod在模块定义的头部直接互相USE对方模块,属于模块级双向依赖。Fortran编译规则要求编译某一模块时,必须先完成所有它USE的模块的编译、生成对应的.mod接口文件,因此两个模块互相等待对方编译完成,陷入死锁。
注:原代码中
MyType2Mod.f90的模块定义行存在笔误,误写为MODULE MyType1Mod,后续改造已修正该问题。
子模块的解决思路
子模块的核心特性是将模块的公开接口声明和具体实现逻辑拆分:
- 父模块仅保留类型定义、过程接口声明,不需要引入对其他模块的依赖
- 具体过程实现放在子模块中,此时才引入对其他模块的依赖
通过这种拆分可以将原来的模块级双向依赖,降级为仅实现层面的依赖,打破编译死锁。
具体改造代码
1. 基础模块MyTypeMod.f90(无需修改)
MODULE MyTypeMod TYPE, ABSTRACT :: MyType INTEGER :: Num END TYPE MyType CONTAINS END MODULE MyTypeMod
2. MyType1父模块MyType1Mod.f90
MODULE MyType1Mod USE MyTypeMod, ONLY : MyType IMPLICIT NONE TYPE, EXTENDS(MyType) :: MyType1 CONTAINS PROCEDURE :: Type1EqualsType2 GENERIC :: ASSIGNMENT(=) => Type1EqualsType2 END TYPE MyType1 ! 仅声明过程接口,不引入对MyType2Mod的依赖 INTERFACE SUBROUTINE Type1EqualsType2(Type1, Type2) IMPORT :: MyType1 TYPE(MyType1), INTENT(OUT) :: Type1 TYPE, INTENT(IN) :: MyType2 END SUBROUTINE Type1EqualsType2 END INTERFACE END MODULE MyType1Mod
3. MyType1实现子模块MyType1Impl.f90
SUBMODULE (MyType1Mod) MyType1Impl USE MyType2Mod, ONLY : MyType2 IMPLICIT NONE CONTAINS MODULE SUBROUTINE Type1EqualsType2(Type1, Type2) TYPE(MyType1), INTENT(OUT) :: Type1 TYPE(MyType2), INTENT(IN) :: Type2 Type1%Num = Type2%Num END SUBROUTINE Type1EqualsType2 END SUBMODULE MyType1Impl
4. MyType2父模块MyType2Mod.f90
MODULE MyType2Mod USE MyTypeMod, ONLY : MyType IMPLICIT NONE TYPE, EXTENDS(MyType) :: MyType2 CONTAINS PROCEDURE :: Type2EqualsType1 GENERIC :: ASSIGNMENT(=) => Type2EqualsType1 END TYPE MyType2 ! 仅声明过程接口,不引入对MyType1Mod的依赖 INTERFACE SUBROUTINE Type2EqualsType1(Type2, Type1) IMPORT :: MyType2 TYPE(MyType2), INTENT(OUT) :: Type2 TYPE, INTENT(IN) :: MyType1 END SUBROUTINE Type2EqualsType1 END INTERFACE END MODULE MyType2Mod
5. MyType2实现子模块MyType2Impl.f90
SUBMODULE (MyType2Mod) MyType2Impl USE MyType1Mod, ONLY : MyType1 IMPLICIT NONE CONTAINS MODULE SUBROUTINE Type2EqualsType1(Type2, Type1) TYPE(MyType2), INTENT(OUT) :: Type2 TYPE(MyType1), INTENT(IN) :: Type1 Type2%Num = Type1%Num END SUBROUTINE Type2EqualsType1 END SUBMODULE MyType2Impl
编译顺序
改造后可按以下顺序无冲突编译:
- 第一步:编译
MyTypeMod.f90 - 第二步:编译
MyType1Mod.f90和MyType2Mod.f90(两者互不依赖,顺序无要求) - 第三步:编译
MyType1Impl.f90和MyType2Impl.f90(两者互不依赖,顺序无要求)
内容的提问来源于stack exchange,提问作者Akhil Akkapelli
相关产品推荐
相关产品推荐

