使用 iso_c_binding 时重命名 Fortran 模块中的子例程
Renaming a subroutine in a Fortran module when using iso_c_binding
我正在使用两个 Fortran 模块。第一个包含子程序 foo
:
module fmod1
contains
subroutine foo(i)
implicit none
integer, intent(inout) :: i
i=i+1
end subroutine foo
end module fmod1
第二个还包含一个名为foo
的子程序,该子程序调用第一个模块的foo
,重命名为foo_first
:
module fmod2
use fmod1, only : foo_first => foo
contains
subroutine foo(i)
implicit none
integer, intent(inout) :: i
i=i+2
call foo_first(i)
end subroutine foo
end module fmod2
当我用 gfortran 编译它们以获得两个目标文件,然后用 nm 查看它们时,我看到了预期的结果:
fmod1.o:
0000000000000020 s EH_frame1
0000000000000000 T ___fmod1_MOD_foo
fmod2.o:
0000000000000030 s EH_frame1
U ___fmod1_MOD_foo
0000000000000000 T ___fmod2_MOD_foo
然后我编写一个 Fortran 程序没有问题,该程序加载第二个模块并在其中调用 foo
(___fmod2_MOD_foo
,它本身调用 ___fmod1_MOD_foo
)。
当我尝试使用 iso_c_binding
从 C 程序做同样的事情时,我的问题就来了。我通过将 bind(c)
添加到子例程来更改第二个模块:
module fmod2
use iso_c_binding
use fmod1, only : foo_first => foo
contains
subroutine foo(i) bind(c)
implicit none
integer, intent(inout) :: i
i=i+2
call foo_first(i)
end subroutine foo
end module fmod2
运行 目标文件上的 nm 现在给出了这个:
fmod1.o:
0000000000000020 s EH_frame1
0000000000000000 T ___fmod1_MOD_foo
fmod2.o:
0000000000000030 s EH_frame1
0000000000000000 T _foo
也就是说,第二个模块似乎不再需要第一个模块。当我尝试从 C 程序的第二个模块调用 foo
时,很明显子例程不是从第一个模块调用 foo
,而是在无限循环中调用自身。
这是一个错误,还是我做了一些我不应该做的事情?
当您将 BIND(C) 添加到过程中时,您是在(间接地)指定绑定名称,而不是编译器应用它自己的规则(包括模块名称)。
不是"the second module no longer seems to require the first module",而是您更改了第二个模块中例程的绑定名称。您还没有在第一个模块中触及 foo 的绑定名称(由于重命名,这不是它的本地名称。)
也就是说,编译器应该知道第一个模块中 foo 的绑定名称,通过它的本地名称引用,并在调用的对象中放入正确的名称。根据其他评论者的说法,您使用的 gfortran 版本可能在此处存在错误。试试更新的。
现在是 GCC Bug 79485. I have already reported very similar and very probably related bugs before (ICE with binding-name equal to the name of a use-associated procedure and Wrong subroutine called, clash of specific procedure name and binding-name)。不幸的是,gfortran 开发人员只有少数而且非常忙,还没有解决这个问题。如果他们看到其他人遇到它,他们可能会考虑稍微高一些的优先级。
我正在使用两个 Fortran 模块。第一个包含子程序 foo
:
module fmod1
contains
subroutine foo(i)
implicit none
integer, intent(inout) :: i
i=i+1
end subroutine foo
end module fmod1
第二个还包含一个名为foo
的子程序,该子程序调用第一个模块的foo
,重命名为foo_first
:
module fmod2
use fmod1, only : foo_first => foo
contains
subroutine foo(i)
implicit none
integer, intent(inout) :: i
i=i+2
call foo_first(i)
end subroutine foo
end module fmod2
当我用 gfortran 编译它们以获得两个目标文件,然后用 nm 查看它们时,我看到了预期的结果:
fmod1.o:
0000000000000020 s EH_frame1
0000000000000000 T ___fmod1_MOD_foo
fmod2.o:
0000000000000030 s EH_frame1
U ___fmod1_MOD_foo
0000000000000000 T ___fmod2_MOD_foo
然后我编写一个 Fortran 程序没有问题,该程序加载第二个模块并在其中调用 foo
(___fmod2_MOD_foo
,它本身调用 ___fmod1_MOD_foo
)。
当我尝试使用 iso_c_binding
从 C 程序做同样的事情时,我的问题就来了。我通过将 bind(c)
添加到子例程来更改第二个模块:
module fmod2
use iso_c_binding
use fmod1, only : foo_first => foo
contains
subroutine foo(i) bind(c)
implicit none
integer, intent(inout) :: i
i=i+2
call foo_first(i)
end subroutine foo
end module fmod2
运行 目标文件上的 nm 现在给出了这个:
fmod1.o:
0000000000000020 s EH_frame1
0000000000000000 T ___fmod1_MOD_foo
fmod2.o:
0000000000000030 s EH_frame1
0000000000000000 T _foo
也就是说,第二个模块似乎不再需要第一个模块。当我尝试从 C 程序的第二个模块调用 foo
时,很明显子例程不是从第一个模块调用 foo
,而是在无限循环中调用自身。
这是一个错误,还是我做了一些我不应该做的事情?
当您将 BIND(C) 添加到过程中时,您是在(间接地)指定绑定名称,而不是编译器应用它自己的规则(包括模块名称)。
不是"the second module no longer seems to require the first module",而是您更改了第二个模块中例程的绑定名称。您还没有在第一个模块中触及 foo 的绑定名称(由于重命名,这不是它的本地名称。)
也就是说,编译器应该知道第一个模块中 foo 的绑定名称,通过它的本地名称引用,并在调用的对象中放入正确的名称。根据其他评论者的说法,您使用的 gfortran 版本可能在此处存在错误。试试更新的。
现在是 GCC Bug 79485. I have already reported very similar and very probably related bugs before (ICE with binding-name equal to the name of a use-associated procedure and Wrong subroutine called, clash of specific procedure name and binding-name)。不幸的是,gfortran 开发人员只有少数而且非常忙,还没有解决这个问题。如果他们看到其他人遇到它,他们可能会考虑稍微高一些的优先级。