gpt4 book ai didi

c - Fortran-C 互操作性和 float 组

转载 作者:行者123 更新时间:2023-12-01 20:04:48 24 4
gpt4 key购买 nike

我有大量现有的 Fortran95 代码。它使用

real(dp), dimension(num) :: array

声明数组。

我想加入一些 C 代码,发现可以通过编写 C 函数接口(interface)并将数组声明为来做到这一点

use iso_c_binding
real(c_double), allocatable, target :: array(:)

我有工作的 fortran 函数,它们将 C 函数调用为

call myfunction(c_loc(array));

real(dp) 数组传递给 myfunction 需要什么?显然,我需要从中创建一个 C 指针(如何?)。除了复制数组还有其他方法吗?是否可以确保这两种类型确实引用兼容的 double 据 block ?最重要的是,该解决方案必须与 GNU 编译器一起工作。请注意,目前我无法在现有 Fortran 代码中将 real(dp) 替换为 real(c_double)

如果没有其他方法可以复制整个数组,我该如何在界面中正确执行此操作?

最佳答案

首先,我假设您将 dp 定义为模块中某处的参数。您只需使用

integer, parameter :: dp = c_double

在该模块中(并在某处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 的包装函数,编译将因缺少通用过程而失败。

关于c - Fortran-C 互操作性和 float 组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28697754/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com