Macros 使用宏替换Fortran子例程名称
我正在编写一个允许用户记录信息的模块。我想提供一个记录字符串消息的接口,它可以被称为Macros 使用宏替换Fortran子例程名称,macros,fortran,Macros,Fortran,我正在编写一个允许用户记录信息的模块。我想提供一个记录字符串消息的接口,它可以被称为 call m_log(msg) 因此,在文件m_logger.f90中,我将 module m_logger .. subroutine m_log(msg) .. end module program main use m_logger call m_log(msg) end program 在main.f90文件中,用户将拥有 module m_logger .. subroutin
call m_log(msg)
因此,在文件m_logger.f90中,我将
module m_logger
..
subroutine m_log(msg)
..
end module
program main
use m_logger
call m_log(msg)
end program
在main.f90文件中,用户将拥有
module m_logger
..
subroutine m_log(msg)
..
end module
program main
use m_logger
call m_log(msg)
end program
现在,我如何用调用m\u日志(msg、\uu文件、\uu行)
替换调用m\u日志(msg)
由于这种替换,将调用记录器模块中不同的子例程子例程m_log(msg,filename,linenum)
如果我使用像#define m_log(msg)m_log(msg,_FILE_uuu,_LINE_u)
这样的宏,则必须将它添加到使用记录器的每个用户文件中
另外,我不想强制用户显式地传递
\uuuuuuuuuuuuuuuuuuuuuuuuuu文件
和行
我有办法做到这一点吗?或者还有其他的选择吗
提前谢谢
编辑:
我讨论了comp.lang.fortran。添加链接以供参考。
如果您不想显式地强制执行\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu文件和和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
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
子程序m_日志(消息、文件名、行数)
字符(len=*)::msg
字符(len=*),可选::文件名
整数,可选::linenum
如果(存在(文件名)),则
恩迪夫
如果(存在(linenum)),则
恩迪夫
结束子程序
如果filename
或linenum
附加了任何值,则内部函数返回真值,否则返回假值。在这种情况下,必须使用C使用的相同方法。定义您建议的宏
#define log(msg) m_log(msg,__FILE__,__LINE__)
在一个单独的文件中(可能与其他有用的宏一起),并使用#include“file.inc”
将其包括在内(标准Fortran include不够)
如果宏的名称与其实际调用的子例程不同,则可以确保用户必须使用include,并且不能忘记它。由于希望用户将它们作为编译器宏传递,因此首先必须为宏选择不同的名称<代码>文件>和都是预定义的宏。这两个宏由预处理器定义,而不是由用户传递。我想这可能会引起一些混乱
如果希望允许用户通过编译器选项选择性地提供宏,则最好在子程序中包含#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文件中,让您的用户始终包含该文件。(类似于弗拉基米尔的回答)这并不能解决我的问题。如果用户没有传递可选参数,我就没有文件名和linenum。那我就误解了你写的内容。我唯一的建议是强烈建议用户在msg
中包含子例程/文件名和行号,并且只使用一个m_log
子例程。您能在这里添加一些说明或示例吗?我很困惑。基本上,我该如何用m\u log(msg,\uuu文件,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?当您说您不希望用户显式地传递参数时,您的意思是用户将把它们定义为环境变量或宏,而不是将它们放在函数调用中吗?\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
和是编译器宏。