如何为Fortran 95+;模块,实现隐藏

如何为Fortran 95+;模块,实现隐藏,fortran,gfortran,fortran95,Fortran,Gfortran,Fortran95,我正在使用gfortran的95+扩展。我有一个实用程序模块库,我想链接到其他项目,即作为库或共享对象/dll。然而,在Fortran中,我不明白如何在不维护模块接口的两个副本的情况下将接口从Fortran中的实现中分离出来 在C中,我会将接口与实现分开,如下所示: api.h ←includes← impl.h ↑ ↑ includes includes ↑ ↑ user.c

我正在使用gfortran的95+扩展。我有一个实用程序模块库,我想链接到其他项目,即作为库或共享对象/dll。然而,在Fortran中,我不明白如何在不维护模块接口的两个副本的情况下将接口从Fortran中的实现中分离出来

在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组(特别是,请参阅)。总之,一种选择是:

  • 将所有库函数/子例程分组在一个文件中,并单独分组(即不属于模块的一部分)

  • 创建一个模块,该模块仅包含要向最终用户公开的子例程的接口

  • 向最终用户提供已编译的模块和库。然后,用户可以
    在其程序中使用
    模块并链接库

这允许您“隐藏”不想向最终用户公开的函数/子例程

从我链接的帖子中提升到:

有些编译器生成.mod(或编译器给它的任何名称)文件和库文件。.mod文件包含符号;库文件包含模块中包含的可执行代码。在这种情况下,必须将这两个文件分发给最终用户

此外,一些编译器(特别是f95)将符号和可执行代码放入单个.mod文件中。在这种情况下,您只需要向最终用户提供.mod文件

(最终!)编辑Fedora wiki上有一个:

理想情况下,可移植Fortran库将避免使用模块。好消息是已经定义了子模块规范,这将允许模块的接口规范部分与过程源代码分离。在[c]e上,这是在Fortran编译器中实现的,所有打包的库都应该使用它


另一种将接口与实现分离并只编写一次的方法是使用
INCLUDE
行将一个源文件的文本包含到另一个源文件中,这是自FORTRAN77(甚至在此之前)以来一直使用的方法。有很多合理的软件工程理由可以避免包含,并且在使用它们时有很多实用性


我应该补充一点,我喜欢Chris已经概述的方法,而不是诉诸于Include,但有时需要…

这取决于你想做什么。如果出于商业机密的考虑,目的是向人们隐藏代码,那么您可以编写“接口”并提供预编译库,而不是实际的代码。用户将使用接口编译文件,以便能够调用您的过程

如果您只是想实践只公开必要内容的良好编程实践,那么可以使用模块,并通过将某些过程或模块变量指定为“私有”来指定模块内部的过程或模块变量。用户可以使用编辑器查看代码,但在模块外无法调用过程。您只能向程序的其余部分披露应该使用的程序,并隐藏其他程序。您可以使用模块顶部的private语句将“private”设为默认值,并指定需要在“public”语句中可见的过程

除非您不希望用户看到或编译源代码,否则我不会提供.mod文件。这就产生了支持各种编译器而不是简单地提供源代码的问题。“private”和“public”语句应该实现两个目标,即不复制接口定义,只公开您需要的接口