文字字符串的 Fortran 宏函数?

Fortran macro function for literal string?

我需要对各种数据类型名称进行一系列子例程调用。例如:

print*, 'Now giving information about Matrix1'
call mysub(Matrix1, size(Matrix1,1), size(Matrix1,2))
print*, 'About to do function on Matrix1'
call dofunction(Matrix1)
print*, 'Matrix1 is a nice matrix! Huzzah!'

print*, 'Now giving information about Matrix2'
call mysub(Matrix2, size(Matrix2,1), size(Matrix2,2))
print*, 'About to do function on Matrix2'
call dofunction(Matrix2)
print*, 'Matrix2 is a nice matrix! Huzzah!'

print*, 'Now giving information about OtherMat'
call mysub(OtherMat, size(OtherMat,1), size(OtherMat,2))
print*, 'About to do function on OtherMat'
call dofunction(OtherMat)
print*, 'OtherMat is a nice matrix! Huzzah!'

并且我想定义一个宏,它将采用 #define 值,以便我可以包装这个调用序列。例如,定义一个宏mymacro,我希望能够简单地调用

mymacro(Matrix1)
mymacro(Matrix2)
mymacro(OtherMat)

完成同样的事情。这可能吗?

写一个这样的子程序怎么样:

subroutine mymacro(matrix, matrixName)
    ! declare matrix, precision should be declare somewhere as a constant
    real(precision), dimension(:,:) :: matrix
    character(*), intent(in) :: matrixname

    print*, 'Now giving information about '//matrixname
    call mysub(matrix, size(matrix,1), size(matrix,2))
    print*, 'About to do function on '//matrixname
    call dofunction(matrix)
    print*, matrixname//' is a nice matrix! Huzzah!'
end subroutine mymacro

它并不是为您命名矩阵的确切名称,但足够接近。

mymacro(matrix)

变成

call mymacro(matrix,'matrix')

差别不大,你不觉得吗?

宏本身不是 Fortran 的一部分。大多数(如果不是全部)编译器通过重用 C 预处理器来实现它们。我从这里学到: https://gcc.gnu.org/onlinedocs/cpp/Macros.html

这可能会奏效:(未测试!)

#define MYSUB(m) write(*,*) "Now giving information about ", #m;  \
                 call mysub(m, size(m,1), size(m,2) ); \
                 write(*,*) "About to do function on ",#m; \
                 call dofunction(m) ; \
                 write(*,*) #m , "is a nice matrix! Huzzah!" ;

请注意,您必须使用适当的编译器标志才能使编译器 运行 成为预处理器。

我花了一段时间才为 gfortran 工作,因为它不支持 #expr

想法是使用; 将多个命令放在一行中。当然,这需要禁用通常的行限制。使用 gfortran,这是通过 -ffree-line-length-0 实现的。

然后,gfortran 的预处理器使用 "x" 而不是 #s(就像所有其他编译器一样)。 这是结果:它正在处理 ifortgfortran

#ifdef __GFORTRAN__

#define mymacro(x) print *, "Now giving information about ", "x" ; \
                   call mysub( x, size(x,1), size(x,2) ) ; \
                   print *, "About to do function on ", "x"; \
                   call dofunction(x) ; \
                   print *, "x"," is a nice matrix! Huzzah!"

#else

#define mymacro(x) print *, "Now giving information about ", #x ; \
                   call mysub( x, size(x,1), size(x,2) ) ; \
                   print *, "About to do function on ", #x; \
                   call dofunction(x) ; \
                   print *, #x," is a nice matrix! Huzzah!"

#endif

program main

implicit none
integer :: i(2,2)

i = 123

mymacro(i)

contains

subroutine mysub(ii, N, M)
  integer,intent(in) :: ii(:,:), N, M
  print *,'in mysub:', ii(1,1)
end subroutine

subroutine dofunction(ii)
  integer,intent(in) :: ii(:,:)
  print *,'in dofunction:', ii(1,1)
end subroutine
end program main