Fortran使用宏替换子程序名称

3
我正在编写一个模块,允许用户记录信息。我想提供一个界面,用于记录字符串消息,可以通过以下方式调用:
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上进行了讨论。 添加一个链接供参考。here

你能否添加一些澄清或示例来说明你在这里尝试实现的内容?我感到困惑。 - Xiaolei Zhu
基本上我怎样才能自动地用宏替换 m_log(msg)m_log(msg,__FILE__,__LINE__) 呢? - Korizon
__FILE____LINE__是什么意思?当你说不想让用户显式地传递参数时,是指用户会将它们定义为环境变量或宏,而不是放在函数调用中吗? - Xiaolei Zhu
__FILE____LINE__是编译器宏。 - Korizon
3个回答

4
在这种情况下,您需要使用与C语言相同的方法。定义您提出的宏。
 #define log(msg) m_log(msg,__FILE__,__LINE__)

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

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


3

如果您不想显式地强制使用__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

内在函数present检查filename或者linenum是否已经有值,如果有则返回真,没有则返回假。


那并不能解决我的问题。如果用户没有传递可选参数,我将无法获得文件名和行号。 - Korizon
1
那我误解了你的意思。我的唯一建议就是强烈建议用户将子程序/文件名和行号包含在msg中,并且只使用一个m_log子程序。 - Kyle Kanos

0

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

如果您希望允许用户通过编译器选项可选地提供宏,则最好在子例程中包含#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的答案)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接