Fortran查询并打印出函数或子程序名称
在 Fortran 中是否可以查询我所在的函数或子例程的名称?即,我用什么来代替“???”让它在屏幕上打印“my_subroutine”?
subroutine my_subroutine()
write(*,*) ???
end subroutine my_subroutine
我试图找到一种方法来实现自定义调试器/分析器,只使用文本编辑器的搜索和替换机制。以编程方式查询我在代码中的位置会很有帮助。
Is it possible in Fortran to query the name of the function or subroutine that I am in? I.e., what do I put in place of '???' to get it to print 'my_subroutine' on the screen?
subroutine my_subroutine()
write(*,*) ???
end subroutine my_subroutine
I am trying to find a way to implement a custom debugger/profiler using nothing but a text editor's search and replace mechanism. Programmatically querying my position in the code would be helpful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用预处理器打印出文件名和行号。您可能需要利用预定义的预处理器符号
__LINE__
和__FILE__
。下面是一个例子:在头文件中定义了一个预处理器宏(以便可以在多个位置使用),将其命名为errormsg.h:
然后您可以将此头文件包含在您的程序、库或模块文件,例如:
ERRORMSG("not true an error...")
对于 Fortran 代码来说似乎是奇怪的语法,但它被使用宏定义的 c 预处理器所取代。因此,编译后,它看起来像:对于我的
ERRORMSG
宏,我选择使用 0 文件单元打印到 stderr。显然,您可以自由地随心所欲地编写消息,只要它能生成语法正确的 FORTRAN 代码即可。要对其进行编译,您需要将标志传递给编译器,并且不同编译器之间的标志略有不同。例如,这对我有用:
也就是说,对于 gfortran,
-cpp
在编译之前调用 c 预处理器。上述程序的输出如下所示:这可能会产生您正在寻找的效果,特别是如果您每个文件只编写一个子例程。
You can use the preprocessor to print out the file name and line number. You might want take advantage of the predefined preprocessor symbols
__LINE__
and__FILE__
. Here's an example:A preprocessor macro is defined in header file (so that it can be used in multiple locations), call it errormsg.h:
Then you can include this header file in your program, library or module files, for example:
The
ERRORMSG("not really an error...")
seems like weird syntax for fortran code, but it get's replaced by the c-preprocessor using the macro definition. So when this is compiled, it looks like:For my
ERRORMSG
macro, I chose to use the 0 file unit to print to stderr. You obviously have the freedom to write the message how ever you like, as long as it results in syntactical correct FORTRAN code.Getting this to compile requires you to pass flags to the compiler, and they differ slightly from compiler to compiler. This worked for me, for example:
That is, for gfortran,
-cpp
invokes the c-preprocessor before compiling. The output from the above program looks like this:This might have the effect you are looking for, especially if you write only one subroutine per file.
不,你不能。您想要实现的目标称为 反射,它在 Fortran 中不可用(也不重要的是用 C 或 C++ 编写)。
No, you can't. What you want to achieve is called reflection and it is not available in Fortran (nor in C or C++ for what matters).
我找到了一种简单的半自动化方法来摆脱这种情况:使用正则表达式在 SUBROUTINE 声明之后添加 __FUNCTION__ 的硬编码定义。从 makefile 中完成将注意每次编译都会刷新 __FUNCTION__ 宏。
假设我们有一个 F77 列表,看起来像这个
文件“my-file.F”,
我想将其转换为
文件“my_file.FF”
请注意,修改后的代码现在位于另一个源文件中:< code>my-file.FF
为此,我将以下几行添加到“Makefile”中,
假设 FC 被定义为 fortran 编译器可执行文件,则应在文件中的所有子例程上执行以下过程
在本例中,结果应为
my-file.o
。您可能已经注意到我也使用了宏 _S()。这是一个“字符串化”宏。你只需要将它添加到你的 fortran 文件的顶部(我将它放在我到处都包含的 config.h 中),
GNU 和 intel 有不同的实现:
I found an easy semi-automated way out of this situation: use regex to add a hardcoded definition of __FUNCTION__ right after the SUBROUTINE declaration. Done from within the makefile will take care that every compilation refreshes the __FUNCTION__ macro.
Suppose we have a F77 listing that looks like this
file 'my-file.F'
I want to convert it to
file 'my_file.F.F'
Note the amended code is now located in another source file:
my-file.F.F
To do this I added the following lines to 'Makefile'
Assuming FC is defined as the fortran compiler executable, this should perform the following procedure on all the subroutines in the file:
The result should be
my-file.o
in this case.You may have noticed that I'm using the macro _S() as well. This is a 'stringify' macro. You just need to add it to the top of your fortran file (I place it inside a config.h that I include everywhere)
There is a different implementation for GNU and intel:
编译器有时会提供非标准功能来帮助您打印当前位置。这些是高度特定于编译器的,只能用于调试。
在 gfortran 中,您可以使用子例程 BACKTRACE。从手册中:
输出看起来像一条错误消息,但它可能会有所帮助。
There are sometimes non-standard features in compilers to help you to print where you currently are. These are highly compiler specific and should be used only for debugging.
In gfortran you can use subroutine BACKTRACE. From the manual:
The output will look like an error message, but it may be helpful.
为什么不在 WRITE 语句中硬写出您所在的子例程的名称呢?
您无法以编程方式(动态)给出或更改子例程的名称,因此我认为没有理由尝试以这种方式访问它(关于这一点:虽然我不确定是否不可能以某种方式访问它,我很确定这是错误的方法......你这样做会给自己带来更多麻烦,而不是仅仅对其进行硬编码)。
顺便说一句,你为什么要打印它呢?措辞良好的诊断消息不是能提供更多信息吗?
Why don't you just hard write the name of the subroutine you're in, in the WRITE statement?
You cannot programmatically (dynamically) give or change the name of the subroutine, therefore I see no reason to try to access it either that way (about that: while I'm not sure that it is impossible to access it somehow, I'm quite sure that it is the wrong way to go ... you will cause yourself more trouble going that way, than just hard coding it).
Btw, why are you trying to print it out anyway? Wouldn't a well phrased diagnostic message be more informative?