Fortran使用宏替换子例程名称



我正在编写一个允许用户记录信息的模块。我想提供一个记录字符串消息的接口,可以称为

call m_log(msg)

所以在m_logger.f90文件中,我会有

module m_logger
..
  subroutine m_log(msg)
  ..
end module 

在文件main.f90中,用户将拥有

program main
use m_logger
call m_log(msg)
end program 

现在如何用call m_log(msg, __FILE__, __LINE__)替换call m_log(msg)

由于这种替换,记录器模块中的另一个子例程subroutine m_log(msg, filename, linenum)将被调用。

如果我使用像#define m_log(msg) m_log(msg,__FILE__,__LINE__)这样的宏,则必须将其添加到使用记录器的每个用户文件中。

此外,我不想强制用户显式传递__FILE____LINE__

有什么办法我能做到这一点吗?或者还有其他选择吗?

提前感谢

编辑:我在comp.lang.fortran上进行了讨论。添加了一个链接以供参考。此处

在这种情况下,您必须使用C使用的相同方法。定义您提出的宏

 #define log(msg) m_log(msg,__FILE__,__LINE__)

在一个单独的文件中(可能与其他有用的宏一起),并使用#include "file.inc"包含它(标准的Fortran include是不够的)。

如果宏的名称与它实际调用的子例程不同,则可以确保用户必须使用include并且不能忘记它。

如果您不想显式强制__file____line__,那么您可以使用可选标志,这样您的子例程看起来像:

subroutine m_log(msg, filename, linenum)
   character(len=*) :: msg
   character(len=*), optional :: filename
   integer, optional :: linenum
   if(present(filename)) then
      <something with filename>
   endif
   if(present(linenum)) then
      <something with linenume>
   endif
   <normal stuff with msg>
end subroutine

如果filenamelinenum附加了任何值,则存在的内部函数将返回true值,否则返回false。

由于您希望它们作为编译器宏由用户传递,因此您必须首先为宏选择不同的名称。CCD_ 12和CCD_。这两个宏是由预处理器定义的,而不是由用户传递的。我认为这可能会引起一些混乱。

如果您希望允许用户通过编译器选项选择性地提供宏,那么最好在您的子例程中包含#ifdef指令:

subroutine m_log(msg)
  implicit none
  character(len=*) :: msg
  character(len=something) :: file
  integer ::line
  !Initialize file and line to some default value
  file=...
  line=...
#ifdef __KVM_FILE__
   file=__KVM_FILE__
#endif
#ifdef __KVM_LINE__
   line=__KVM_LINE__
#endif
   ...

这样,用户将始终使用相同的语法call m_log(something)调用子例程,但效果会根据编译宏而变化。当然,这也需要用户在每次更改此宏时重新编译代码。如果这样做成本太高,可以设置一个带有可选参数的子例程(如Kyle的回答),然后将#define宏包含在#ifdef块中,并将它们放入.h文件中,让用户始终包含该文件。(类似于Vladimir的回答)

最新更新