Fortran求根子程序报错时如何输出传入的实际目标函数名
问题结论
Fortran 标准原生不支持自动获取作为参数传入的过程的源代码名称:过程作为实参传递时仅传递执行入口地址,不会携带函数名这类源代码层面的元数据,无法在mysolver内部直接解析出传入的FN对应的实际函数名。
可落地实现方案
最通用、可移植性最好的方式是为子程序额外增加一个字符串类型的入参,由调用方显式传入目标函数的名称,报错时直接输出该字符串即可。
修改后的子程序代码
subroutine mysolver(xl,xr,FN, fname, x_sol) real, intent(inout) :: xl,xr real, intent(out) :: x_sol real :: fl,fr ! 新增:用于接收目标函数名称的字符串参数 character(len=*), intent(in) :: fname interface real function FN(y) real, intent(in) :: y end function FN end interface fl = FN(xl) fr = FN(xr) if (fl*fr > 0.0) then ! 输出时用trim去掉字符串尾部多余空格 print *, 'Error solving function ', trim(fname) end if ! 其余原有求解逻辑保持不变 end subroutine mysolver
调用方式
调用求解器时,把对应目标函数的名字作为字符串传入即可:
! 假设存在两个待求解的目标函数func1、func2 ! 求解func1时 call mysolver(xl, xr, func1, 'func1', x_sol1) ! 求解func2时 call mysolver(xl, xr, func2, 'func2', x_sol2)
简化写法(依赖预处理,非标准特性)
如果不想每次手动输入函数名字符串,可以开启编译器的预处理支持,用宏做一层封装自动填充函数名字符串,以常用的C预处理器(绝大多数Fortran编译器都支持)为例:
! 注意:开启预处理时该宏定义要写在函数声明之前 #define MYSOLVER(xl, xr, fn, x_sol) mysolver(xl, xr, fn, #fn, x_sol)
封装后调用时不需要手动写名字符串,直接写:
call MYSOLVER(xl, xr, func1, x_sol1) call MYSOLVER(xl, xr, func2, x_sol2)
预处理器会自动把#fn替换为对应实参的字符串形式"func1"/"func2"。注意该方案依赖编译器预处理能力,跨编译器时需要确认适配性。
不推荐尝试通过过程内存地址反查符号名的方案:这类方案需要调用操作系统/调试器相关的底层API,实现复杂度极高,跨平台、跨编译选项(比如开启优化后符号表可能被剥离)兼容性极差,完全没有必要。
内容的提问来源于stack exchange,提问作者Looper
相关产品推荐
相关产品推荐

