【问题标题】:Passing Fortran array via ISO_C_BINDING通过 ISO_C_BINDING 传递 Fortran 数组
【发布时间】:2014-05-21 21:26:57
【问题描述】:

我正在尝试获取 Fortran 代码库以使用 ISO_C_BINDING 调用 C 库调用,但在传递 Fortran 数组时遇到问题。

我创建了一个简单的例子来说明我的问题。

main.f90

program main
    use iso_c_binding
    implicit none

    interface
            subroutine stuff(s,d) bind(c,name='doStuff')
                    import :: c_char
                    import :: c_ptr
                    import :: c_double

                    character(c_char), value :: s
                    type(c_ptr), value :: d
            end subroutine stuff
    end interface

    character(len=1) ::c1
    real, allocatable :: d1(:)

    c1 = 'a'
    allocate ( d1(0:10) )

    d1(0) = 2.0
    d1(1) = 2.5
    d1(2) = 3.0
    d1(3) = 4.0

    write (*,*) d1

    call stuff(c1,c_loc(d1))

end program main

func.c

//a function
int doStuff (char c, double* w)
{
    printf("%c\n",c);
    printf("%d %d %d %d\n",w[0], w[1], w[2], w[3]);
    return 1;
}

编译行

icc -c func.c
ifort -o magic.go main.f90 func.o

输出

2.000000       2.500000       3.000000       4.000000      0.0000000E+00    0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00
a
0 -1938231792 1 1

char 被正确传递,但数组没有被正确传递,我不知道如何更正它。我看到的例子暗示了改变

double* w

void* w

但我不能这样做,因为我无法更改库代码来完成这项工作。我只是尝试创建一个新函数来将void* 转换为double* 无效:(。 同样,将数组更改为不可分配也是不可行的。

想法?

【问题讨论】:

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


【解决方案1】:

d1 的声明有问题。会更好

real(c_double), allocatable, target :: d1(:)

也就是说:它必须是正确的类型才能与 C 的 double 互操作;要成为c_loc 的参数,它必须具有targetpointer 属性。

此外,正如 Mahonri Moriancumer 所指出的,您的 printf 格式不适合双精度。而且,可能值得考虑将stuff 作为函数而不是子例程。

【讨论】:

  • 最重要的部分是real(c_double):我只是惊讶于ifort 对c_loc 的属性如此漠不关心。
  • 为什么这里需要target 属性?我用target属性测试过,代码还是可以正常工作
  • @SangjunLee,Fortran 标准(参见 F2018 18.2.3.6)需要目标或指针属性作为 c_loc 的参数。尽管某些编译器(尤其是 ifort)并不关心并且似乎可以正常工作,但为了最大程度地提高正确性和可移植性,最好拥有这些属性之一。
猜你喜欢
  • 2014-10-25
  • 1970-01-01
  • 2017-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
相关资源
最近更新 更多