我有一个很大的现有Fortran95代码。 它用
real(dp), dimension(num) :: array
声明数组。
我想加入一些C代码,发现我可以通过将接口写入C函数并将数组声明为
use iso_c_binding real(c_double), allocatable, target :: array(:)
我有工作的fortran函数,它们将C函数称为
call myfunction(c_loc(array));
将real(dp)
数组传递给myfunction需要什么? 显然,我需要从它做一个C指针(如何?)。 除了复制数组之外还有其他方法吗? 是否可以确保两种类型确实引用兼容的双精度数据块? 最重要的是,该解决方案必须与GNU编译器一起使用。 注意,在现有的Fortran代码中用real(c_double)
替换real(dp)
并不是我现在的选择。
如果没有其他方法可以复制整个arrays,我将如何在界面中正确执行此操作?
首先,我假设您将dp定义为某个模块中的参数。 你可以简单地使用
integer, parameter :: dp = c_double
在那个模块中(并且if (dp /= c_double) stop "Bletchful sytem"
某处if (dp /= c_double) stop "Bletchful sytem"
。
在C和Fortran之间传递数组的工作方式如下:
module foo use iso_c_binding private public :: bar interface subroutine bar(a,n) bind(C) import real(kind=c_double), dimension(*), intent(inout) :: a integer(c_size_t), value, intent(in) :: n end subroutine bar end interface end module foo
那么你的C函数就是
void bar(double *a, size_t n)
编辑:
那么从Fortran调用C函数的方法就是
program main use iso_c_binding use foo real(c_double), dimension(10) :: a call bar(a,size(a,kind=c_size_t)) print *,a end program main
编辑2:
如果你真的想每次都进行复制/复制,你可以做类似的事情
subroutine bar2(array) real(kind=c_double), intent(inout), dimension(:) :: array real(kind=c_double), dimension(size(array)) :: a a = array ! Copy in call bar(a,size(a,kind=c_size_t)) array = a ! Copy out end subroutine bar2 end module foo
但我不知道为什么这是必要的。
编辑3:
如果您害怕C和Fortran数据类型之间的不匹配,您可以编写一个通用的包装器来解决这个问题。 这就是它的样子:
module foo use iso_c_binding implicit none private public :: bar interface subroutine bar_double(a,n) bind(C) import real(kind=c_double), dimension(*), intent(inout) :: a integer(c_size_t), value, intent(in) :: n end subroutine bar_double end interface interface subroutine bar_float(a,n) bind(C) import real(kind=c_float), dimension(*), intent(inout) :: a integer(c_size_t), value, intent(in) :: n end subroutine bar_float end interface interface bar module procedure bar_aux_double, bar_aux_float end interface bar contains subroutine bar_aux_double (a) real(kind=c_double), dimension(:), intent(inout) :: a call bar_double (a, size(a,kind=c_size_t)) end subroutine bar_aux_double subroutine bar_aux_float (a) real(kind=c_float), dimension(:), intent(inout) :: a call bar_float (a, size(a,kind=c_size_t)) end subroutine bar_aux_float end module foo
然后你的主程序可能会像
program main use foo integer, parameter :: dp = selected_real_kind(15) integer, parameter :: sp = selected_real_kind(6) real(dp), dimension(10) :: a_dp real(sp), dimension(10) :: a_sp call bar(a_dp) call bar(a_sp) print *,a_dp,a_sp end program main
在那里你根本没有提到iso_c_binding。 如果dp或sp没有包装函数,则由于缺少通用过程,编译将失败。
如果你使用模块,在Fortran中混合dp
和c_double
时不要太担心。 在selected_real_kind(15, 307) /= c_double
的极不可能的情况下,编译器在检查过程接口时会抱怨。 否则,它将看到类型数字一致,并且它不关心您如何调用类型常量(除非声明可互操作的过程)。
需要了解更多c/c++开发分享Fortran-C互操作性和浮点数组,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!
以上就是c/c++开发分享Fortran-C互操作性和浮点数组相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/979110.html