【问题标题】:Check for ISO_C_BINDING usage in Fortran calling C function检查 Fortran 调用 C 函数中的 ISO_C_BINDING 用法
【发布时间】:2020-09-16 04:50:22
【问题描述】:

我在ISO_C_BINDING 上问了几个问题,我做了一个例行公事。由于我在处理 Fortran POINTER 时总是犯很多错误,所以我想确保没有错误或一些不推荐的奇怪点。

(Fortran 部分)

program test
  use iso_c_binding
  implicit none
  interface
    subroutine get_value_array(in, num) bind(C, name='get_value_Array')
      use iso_c_binding
      implicit none
      type(C_PTR),           intent(inout)  :: in
      integer(C_INT), value, intent(in)     :: num
    end subroutine
  end interface

  real(C_DOUBLE), allocatable, target  :: array(:)
  real(C_DOUBLE),              pointer :: array_fptr(:)
  type(C_PTR)                          :: array_cptr

  integer :: array_len

  allocate(array(12))
  array_len = size(array,1)

  array_cptr = C_LOC(array)

  call get_value_array (array_cptr, array_len)

  call C_F_POINTER(array_cptr, array_fptr, [array_len])

  print *, 'array_fptr'
  print *, array_fptr

  print *, 'array'
  print *, array

end program

(C部分)

void get_value_Array(double **in, int num) {
  int i;
  for (i = 0; i < num; i++) {
    (*in)[i] = i+1;
  } 
} 

(输出)

 array_fptr
   1.00000000000000        2.00000000000000        3.00000000000000
   4.00000000000000        5.00000000000000        6.00000000000000
   7.00000000000000        8.00000000000000        9.00000000000000
   10.0000000000000        11.0000000000000        12.0000000000000
 array
   1.00000000000000        2.00000000000000        3.00000000000000 
   4.00000000000000        5.00000000000000        6.00000000000000 
   7.00000000000000        8.00000000000000        9.00000000000000 
   10.0000000000000        11.0000000000000        12.0000000000000 

为了确定,这个过程是

  1. array_cptr 通过 C_LOC 函数与 array 相关联。 (也许“关联”在这里不是一个合适的术语,因为它是与 Fortran 指针相关的术语。我应该怎么称呼它?)
  2. array 在我调用 get_value_array 时被修改,因为子例程(或 C 函数)修改了 array_cptr 指向的位置。
  3. 当我打电话给C_F_POINTER 时,array_fptr 通过array_cptrarray 相关联

最后array_cptrarray_fptr 是彼此不同的对象(?),同时指向同一个目标array,对吧?

【问题讨论】:

    标签: c pointers fortran fortran-iso-c-binding


    【解决方案1】:

    问题中的陈述模棱两可。准确地说。

    1. 使用 Fortran 语句 array_cptr = C_LOC(array)array_cptr 被分配了 array 的 C 地址。

    2. get_value_array被调用时,array的值最终会被C函数修改。 Fortran 代码还允许子例程(或 C 函数)修改存储在 array_cptr 中的 C 地址 - 虚拟参数被声明为 INTENT(INOUT) 并且没有 VALUE 属性,并且与 C 函数一致通过引用获取指向数组的指针(即,C 形式参数被声明为指向双精度指针的指针)。但是 C 函数不会对存储在 array_cptr 中的 C 地址进行此​​类修改。对于显示的代码,存在不必要的间接级别。

    3. Fortran 代码将array_fptrarray_cptr 中的C 地址所引用的事物相关联。因为array_cptr 中的C 地址没有被C 函数改变,array_fptr 继续与array 关联。在这种情况下执行 C_F_POINTER 不会改变程序的状态。

    array_cptrarray_fptr 不同——但它们具有相同的目标(array_cptr 是一个对象,array_fptr 与一个对象相关联——Fortran 中的指针本身并不是对象,这与 C 中的不同)。

    【讨论】:

    • 谢谢,您的回复对我澄清代码中的内容很有帮助。用“2”。在您的回答中,您的意思是 array_cptr 被声明为 INTENT(INOUT) 是不必要的,因为它的值本身不会改变? (而 array 存储在地址指向的位置被修改)。将array_cptr 设置为 INTENT(IN) 确实没有问题,而将其设置为VALUE, INTENT(IN) 会导致段错误。除此之外,我的代码大部分都没有错误,不是吗? (这里不必要的间接是因为我的目标 C 函数将 ** 作为它的参数。)
    • 是的。如果添加了 VALUE,则需要从 C 函数中移除一层间接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 2014-10-25
    • 1970-01-01
    相关资源
    最近更新 更多