使用 GCC 对模块内的 fortran 子例程进行外部命名

Posted

技术标签:

【中文标题】使用 GCC 对模块内的 fortran 子例程进行外部命名【英文标题】:External naming of fortran subroutine inside a module using GCC 【发布时间】:2018-06-22 14:11:21 【问题描述】:

我的目标是重命名模块内的 fortran 子例程,使其易于被 C 代码调用(即不带 __<modulename>_MOD_ 前缀),并使用 GCC-6.3.0。我不能使用bind(c,name=''),即使它很好用。我读过我应该使用界面,但没有任何成功。这是 MWE:

module testmodule
    interface
       subroutine func02
       !GCC$ ATTRIBUTES CDECL :: func01
       end subroutine
    end interface

    contains

    subroutine func01
      print*,"func01"
    end subroutine
end module 

我使用命令gfortran -c test.f90 进行编译,然后使用nm test.o 检查子例程是否正确重命名,但没有func02 的迹象。 任何帮助表示赞赏。

【问题讨论】:

您是否尝试过使用 DLLEXPORT 属性? 为什么不能使用bind(c)?任何阻止您使用的东西也可能阻止您使用任何其他建议,因此您澄清一下会很有用。 @RodrigoRodrigues DLLEXPORT 也不起作用。我也在Linux上工作。 @francescalus 超过 10000 行代码具有很高的复杂性,使用 bind(c) 改变了许多从 c 结构开始的东西,这些东西从 C 传输到 Fortran 非常不同(使用 void *)。我需要这个特定的 MWE 才能工作。感谢您对这个问题的兴趣。 如果 BIND(C) 对您的程序的性质进行了一些重要的更改,那么您的示例需要包含这些更改,以便我们可以为您提供适当的建议。如果您有现有的 C 代码调用现有的 Fortran 过程,但有一个很长有趣的 MOD 名称,那么构造 BIND(C) 包装器应该是相当直接的(您不必更改原始 Fortran - 您可以添加另一个过程作为中间过程)为保持二进制兼容性的现有过程,禁止名称。 【参考方案1】:

您可以使用 BIND(C) 重命名子程序。无论您读到什么关于 INTERFACE 的内容似乎都是在转移注意力。

module testmodule
   contains
      subroutine func01() bind(c, name='func2')
         print*,"func01"
      end subroutine
end module

使用简单的命令“gfortran -c a.f90”,我看到以下结果

nm a.o
     U _gfortran_st_write
     U _gfortran_st_write_done
     U _gfortran_transfer_character_write
00000000 T func2

【讨论】:

对不起,我已经解释过 bind(c) 对我来说是禁止的。我同意你的代码有效,但它不适合我。 @ThomasGuenet,你是​​什么意思禁止? 我无法使用它,因为复杂的 fortran 代码结构意味着更改太多代码。因此bind(c) 是任何人开始新项目的解决方案,但我要求另一种解决方案:这是这个问题的目的。 您可以在一个地方使用bind(c) 来生成正确的绑定名称,而不是在其他任何地方使用它。我不明白bind(c) 会如何对您的代码库的其余部分造成任何问题。 @evets,这不是不可能的。 ThomasGuenet,您可以使用 gfortran 生成程序集文件。通过 sed 提供该文件以去除前缀。然后使用 gfortran 编译 sed 编辑的程序集。祝你好运,或者使用 BIND(C)。

以上是关于使用 GCC 对模块内的 fortran 子例程进行外部命名的主要内容,如果未能解决你的问题,请参考以下文章

fortran 模块的子例程名称冲突

在Fortran中正确使用模块,子例程和函数

使用宏的 Fortran 替换子例程名称

在 C++ 和 Fortran 代码之间传递复数数组

在 FORTRAN 子例程中传递不同的变量集

C++ 从 dll 调用 FORTRAN 子例程