预处理器和使用关联

Posted

技术标签:

【中文标题】预处理器和使用关联【英文标题】:Preprocessors and use association 【发布时间】:2012-02-28 17:37:51 【问题描述】:

总而言之,是否可以通过使用关联访问在 Fortran 模块中定义的预处理器指令?

上下文

我使用预处理器语句来定义子例程来打印警告和错误消息。例如,我在文件errors.f 中使用以下模块/子例程来打印警告消息

module errors
  use, intrinsic :: iso_fortran_env, only : error_unit=>stderr
  implicit none
  contains

    !> Print formatted warning message.
    subroutine warn_print( file, line, mesg )
      implicit none
      character(len=*), intent(in) :: file
      integer,          intent(in) :: line
      character(len=*), intent(in) :: mesg

      write(stderr,'(a,a,a,i4,a,a)') "WARNING::", file, ":", line, ": ", mesg

  end subroutine warn_print

end module errors

并且,在一个单独的文件errors.h中,我use上面的模块并定义了一个预处理器宏

use errors

#define warn( text )warn_print(__FILE__,__LINE__,text)

然后我 #include 文件 errors.h 在我希望使用允许我简单编写的警告打印例程的任何文件/模块中

call warn("Some warning message")

编译器将自动包含调用警告消息的文件和行号。

问题

#include 'errors.h' 在 Fortran 代码中的使用相当特殊,它隐藏了 errors 模块的 use。理想情况下,我更愿意在错误模块本身中定义上述预处理器。但是,当使用该模块时,此预处理器指令不适用于 uses 此模块的程序/模块。

有没有办法通过使用关联使预处理器指令可访问?

我能想到的唯一其他方法是只使用错误模块并在我对编译器的调用中定义预处理器指令(例如,使用带有 ifort 的 -D 标志)。任何关于实现上述任何替代方法的建议将不胜感激。

【问题讨论】:

【参考方案1】:

不,这根本不可能,因为预处理和编译阶段是完全分开的,而且 C 预处理器对 Fortran USE 语句一无所知。

我在我的大多数 .F90 源代码中都使用 #include 'config.h'(来自 autoconf),没有问题。

【讨论】:

我想了很多,这就是为什么我使用我在问题中描述的设置。我希望获得其他人对不同方案的建议,以实现打印调用它的文件和行号的函数。欢迎来到 So!【参考方案2】:

这可能不是你想要的,但如果你使用 ifort,你可以使用回溯功能来实现类似的东西(更强大一点,但也更丑陋),例如

program tracetest
  call sub(5)
  write(*,*) '=== DONE ==='
end program tracetest

subroutine sub(n)
  use ifcore
  integer :: n
  character(len=60) :: str
  write(str,*) '=== TROUBLE DETECTED: n =',n  ! code -1 means "do not abort"      
  call tracebackqq(str,-1)    
end subroutine sub

然后,使用-traceback 编译以查看源文件、行和堆栈跟踪。由于内联,堆栈跟踪和行可能会被遮挡;为避免这种情况,您可以指定-traceback -O0 来获得这样的信息:

=== TROUBLE DETECTED: n =           5                      
Image              PC                Routine            Line        Source             
a.out              0000000000473D0D  Unknown               Unknown  Unknown
a.out              0000000000472815  Unknown               Unknown  Unknown
a.out              0000000000423260  Unknown               Unknown  Unknown
a.out              0000000000404BD6  Unknown               Unknown  Unknown
a.out              0000000000402C14  sub_                       12  tracetest.f90
a.out              0000000000402B18  MAIN__                      2  tracetest.f90
a.out              0000000000402ADC  Unknown               Unknown  Unknown
libc.so.6          000000323201EC5D  Unknown               Unknown  Unknown
a.out              00000000004029D9  Unknown               Unknown  Unknown
=== DONE ===

或者,如果想要保留优化,并且还想看到正确的行 (12),您可以使用(例如)-fast -traceback -debug all,inline_debug_info 进行编译。其他编译器中可能有类似的东西,但我不确定。

【讨论】:

谢谢@laxxy - 我对此一无所知。这是一个很好的答案,但不幸的是不便携。看看是否有此功能的等效/类似便携式版本会很有趣。

以上是关于预处理器和使用关联的主要内容,如果未能解决你的问题,请参考以下文章

C预处理器和C库--1

使用日期选择器和时刻处理不同语言的日期

ccache 预处理器和直接模式有啥区别?

python学习--迭代器和异常处理

1.预处理器,编译器,汇编器和链接器

KEIL编译器预处理器和预定义宏(include,ifdef,def等)