【发布时间】:2015-06-03 12:49:19
【问题描述】:
我有多个带有参数 p 的子例程,它是一个显式大小的数组,例如
subroutine foo(p)
integer,dimension(2),intent(in) ::p
end subroutine foo
subroutine bar(p)
integer,dimension(3),intent(in) ::p
end subroutine bar
我想通过间接调用来调用这两个函数,但是找不到一种方法来声明一个同时匹配 foo 和 bar 签名的接口...
例如在界面中使用假定的数组大小是行不通的:
subroutine indirect(f,p)
integer,dimension(*),intent(in):p
interface
subroutine f(p)
integer,dimension(*),intent(in) :: p
end subroutine f
end interface
call f(p)
end subroutine indirect
当我通过间接调用 foo 或 bar 时,编译器 (gfortran 4.9.2) 抱怨 f 的第一个参数 p 的形状不匹配...
integer,dimension(2) :: pfoo
integer,dimension(3) :: pbar
pfoo = (/ 0,1 /)
pbar = (/ 1,2,3 /)
call foo(pfoo) ! direct call is OK
call bar(pbar)
call indirect(foo,pfoo) ! compiler complains about foo signature
call indirect(bar,pbar) ! same for bar...
编译器错误类似于:
Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'p'
当然,我可以修改 foo 和 bar 签名以使用假定的数组大小 (*) 而不是固定的数组大小,但是
这就像我丢失了一些信息只是为了制作编译器 快乐而不增加任何安全性
foo 和 bar 不是我的代码,我不想更改它们...
我找到了一种解决方法,但它包括为每个子例程 foo 和 bar 编写一个假定大小的包装器
call indirect(foo_wrapper,pfoo) ! compiler complains about foo signature
call indirect(bar_wrapper,pbar) ! same for bar...
subroutine foo_wrapper(p)
integer,dimension(*),intent(in) ::p
call foo(p)
end subroutine foo_wrapper
subroutine bar_wrapper(p)
integer,dimension(*),intent(in) ::p
call bar(p)
end subroutine bar_wrapper
或者最终,用间接和包装器中的延迟大小替换所有假定的大小,以便有机会进行运行时检查,也可以,但这不是重点......
关键是,因为我有很多这样的 foo/bar,所以没有办法正确声明接口(我的意思是没有包装器或其他人工制品)。
我无法破译标准(我使用了 http://www.j3-fortran.org/doc/year/10/10-007.pdf - 我认为它大约是 12.5.2.9 与虚拟过程实体相关的实际参数 §2),所以我不知道它是否是gfortran 的限制。现在我没有任何其他可用的编译器,但我想知道是否有其他编译器可以编译(英特尔?-我在 windows 7 64 位上)。
【问题讨论】:
-
注意:
(*)是假定的大小,而不是假定的形状。区别其实很重要。假定形状为(:)。 -
@VladimirF 谢谢,已更正,我被编译器错误消息滥用了