如何为Fortran 95+;模块,实现隐藏
我正在使用gfortran的95+扩展。我有一个实用程序模块库,我想链接到其他项目,即作为库或共享对象/dll。然而,在Fortran中,我不明白如何在不维护模块接口的两个副本的情况下将接口从Fortran中的实现中分离出来 在C中,我会将接口与实现分开,如下所示:如何为Fortran 95+;模块,实现隐藏,fortran,gfortran,fortran95,Fortran,Gfortran,Fortran95,我正在使用gfortran的95+扩展。我有一个实用程序模块库,我想链接到其他项目,即作为库或共享对象/dll。然而,在Fortran中,我不明白如何在不维护模块接口的两个副本的情况下将接口从Fortran中的实现中分离出来 在C中,我会将接口与实现分开,如下所示: api.h ←includes← impl.h ↑ ↑ includes includes ↑ ↑ user.c
api.h ←includes← impl.h
↑ ↑
includes includes
↑ ↑
user.c impl.c
在现代Fortran中有没有一种方法可以达到同样的效果?我是否需要为我的库用户提供.mod文件
- 显式接口的单一定义
- 只有接口定义才对用户代码公开
- .mod文件是必需的,因为它们包含显式接口定义
- 模块没有标准的Fortran ABI--.mod文件将是特定于编译器的
- 实现隐藏问题的唯一直接分析方法是子模块,它在Fortran 2008中定义,gfortran不支持
- @High-Performance Mark和Fedora页面指出,除了避免模块之外,最实用的方法是分发仅用于接口的模块的include文件以及用于实现的预编译.mods
- 使用includes会出现一些众所周知且令人恼火的问题,包括公共块的潜在重新定义
我有点惊讶,这里实际上没有一个简单的答案。我相信使用Fortran 2008编译器可以做到这一点。来自FortranWiki: 子模块是Fortran 2008的一项功能,它允许模块过程在模块中定义其接口,而过程主体在单独的单元(子模块)中定义 来自(我的) [子模块允许]在单独的程序单元中表示模块的规范和实现,这改进了大型库的打包,允许在发布最终接口时保留商业机密,并防止编译级联 我没有任何子模块的经验,它们还没有得到广泛的支持,但它们是需要注意的 编辑由于许多编译器不支持子模块,讨论其他选项可能会有所帮助 问了一个与此类似的问题,并且有很多不错的链接。特别有用的是在讨论Google组(特别是,请参阅)。总之,一种选择是:
- 将所有库函数/子例程分组在一个文件中,并单独分组(即不属于模块的一部分)
- 创建一个模块,该模块仅包含要向最终用户公开的子例程的接口
- 向最终用户提供已编译的模块和库。然后,用户可以
模块并链接库在其程序中使用
另一种将接口与实现分离并只编写一次的方法是使用
INCLUDE
行将一个源文件的文本包含到另一个源文件中,这是自FORTRAN77(甚至在此之前)以来一直使用的方法。有很多合理的软件工程理由可以避免包含,并且在使用它们时有很多实用性
我应该补充一点,我喜欢Chris已经概述的方法,而不是诉诸于Include,但有时需要…这取决于你想做什么。如果出于商业机密的考虑,目的是向人们隐藏代码,那么您可以编写“接口”并提供预编译库,而不是实际的代码。用户将使用接口编译文件,以便能够调用您的过程 如果您只是想实践只公开必要内容的良好编程实践,那么可以使用模块,并通过将某些过程或模块变量指定为“私有”来指定模块内部的过程或模块变量。用户可以使用编辑器查看代码,但在模块外无法调用过程。您只能向程序的其余部分披露应该使用的程序,并隐藏其他程序。您可以使用模块顶部的private语句将“private”设为默认值,并指定需要在“public”语句中可见的过程 除非您不希望用户看到或编译源代码,否则我不会提供.mod文件。这就产生了支持各种编译器而不是简单地提供源代码的问题。“private”和“public”语句应该实现两个目标,即不复制接口定义,只公开您需要的接口