通过ISO_C_BINDING传递Fortran数组

时间:2014-05-21 21:26:57

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

我正在尝试使用ISO_C_BINDING来调用C语言调用Fortran代码库,但是我在传递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*无效:(。 同样地改变数组以使其不可分配是不可行的。

思想?

1 个答案:

答案 0 :(得分:2)

您对d1的声明有疑问。更好的是

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

那就是:它需要是与C的双重互操作的正确类型;要成为c_loc的参数,它必须具有targetpointer属性。

另外,正如Mahonri Moriancumer所述,您的printf格式不适合双重格式。并且,可能将stuff作为函数而不是子例程可能值得考虑。