我正在使用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页面提供的最实用的方法是分发仅用于接口模块的包含文件以及用于实现的预编译.mods。
使用includes有一些众所周知且烦人的旅行,包括可能重新定义公共块。
我有点惊讶的是,这里没有一个直截了当的答案。
答案 0 :(得分:5)
我相信您可以使用Fortran 2008编译器submodules执行此操作。来自FortranWiki:
子模块是Fortran 2008的一个功能,它允许模块过程在模块中定义其接口,同时在单独的单元(子模块)中定义过程的主体。
来自Wikipedia(强调我的)
[子模块允许]模块的规范和实现以单独的程序单元表示,这改进了大型库的包装,允许在发布确定接口时保护商业机密,并防止编译级联
我对子模块没有任何经验,但它们还没有被广泛支持,但它们是值得注意的。
编辑由于许多编译器不支持子模块,因此讨论其他选项可能会有所帮助。
This page向此提出了类似的问题,并提供了许多不错的链接。在讨论Google网上论坛时特别有用(特别参见this post)。总之,一种选择是:
将所有库函数/子例程分组到一个文件中并自行分组(即不是模块的一部分)。
创建一个模块,该模块仅包含您希望向最终用户公开的子例程的接口。
为最终用户提供已编译的模块和库。然后,用户可以在他/她的程序中use
模块并链接到库。
这允许您“隐藏”您不希望向最终用户公开的函数/子例程。
从帖子中解除我链接到:
某些编译器生成.mod(或编译器给它的任何名称)文件和库文件。 .mod文件包含符号;库文件包含模块中包含的可执行代码。在这种情况下,您必须将这两个文件分发给最终用户。
此外,一些编译器(特别是f95)将符号和可执行代码放入单个.mod文件中。在这种情况下,您只需要向最终用户提供.mod文件。
(最终!)编辑 Fedora维基上有一个useful page:
理想情况下,可移植的Fortran库将避免使用模块。好消息是已经定义了一个子模块规范,它允许模块的接口规范部分与过程源代码分开。在[c] e这是在Fortran编译器中实现的,它应该被所有打包的库使用。
答案 1 :(得分:2)
另一种将接口与实现分离并且只为每次编写一次的方法,自FORTRAN77以来(甚至可能在此之前)使用的方法是使用INCLUDE
行来包含一个源的文本将文件存入另一个源文件。避免INCLUDE有很多合理的软件工程原因,并且在使用它们方面有很多实际应用。
我应该补充一点,我喜欢克里斯已经概述的方法,而不是诉诸INCLUDE,但有时需要......
答案 2 :(得分:2)
这取决于你想做什么。如果意图是因为商业机密而隐藏代码,那么您可以编写“接口”并提供预编译库而不是实际代码。用户可以使用接口编译文件以便能够调用您的过程。
如果您只想练习良好的编程实践,只展示必要的内容,您可以使用模块,并通过将模块指定为“私有”来指定模块内部的某些过程或模块变量。一个人可以使用编辑器查看代码,但程序不能在模块外部调用。您只能向程序的其余部分披露应该使用的程序并隐藏其他程序。您可以使用模块顶部的私有语句将“private”设置为默认值,并指定需要在“public”语句中显示的过程。
除非您不希望用户查看或编译源代码,否则我不会提供.mod文件。这就产生了支持各种编译器的问题,而不是简单地提供源代码。 “私有”和“公共”语句应该实现两个目标:不重复接口定义,只暴露您希望暴露的接口。除非您的程序非常大或存在其他问题,否则其他方法对我来说似乎过于复杂。