C_F_POINTER导致未定义的数组

时间:2014-01-28 08:51:54

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

I have tried to modify code from this this question到ISO_C_BINDING,但C_F_POINTER调用导致未定义的指针/数组(VS2010调试器)和print*, f_arr(i)触发分段错误。我想我确实密切关注the array interop的指示。

的main.c

extern void subr(int, float*);
int main(int argc, char **argv){
    int N = 3;
    int i;
    float data[3];
    for (i=0;i<N;i++) data[i]=i;
    subr(N,data);
}

sub.f90

subroutine subr(n, c_arr) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING 
implicit none

INTEGER(C_INT),VALUE :: n
TYPE (C_PTR) :: c_arr
REAL(C_FLOAT), POINTER :: f_arr (:)
integer :: i,ml,mu

CALL C_F_POINTER (c_arr, f_arr, (/n/) )
ml = lbound(f_arr,1)
mu = ubound(f_arr,1)

do i=ml,mu
  print*, f_arr(i)
enddo
end subroutine

你知道为什么我的指针转换失败了吗? (英特尔fortran编译器)

1 个答案:

答案 0 :(得分:4)

通过英特尔文档中的ISO_C_BINDING从C调用Fortran的示例不是很清楚。但是elsewhere,我发现了这个解释:TYPE (C_PTR) :: X等同于C void **,即指向void指针的指针。我们需要void *,一个void指针,因此必须使用C_ARR属性声明VALUE

SUBROUTINE SUBR(N, C_ARR) BIND(C)
    USE, INTRINSIC :: ISO_C_BINDING 
    IMPLICIT NONE

    INTEGER (C_INT), VALUE :: N
    TYPE (C_PTR), VALUE :: C_ARR
    REAL (C_FLOAT), POINTER :: F_ARR(:)

    CALL C_F_POINTER(C_ARR, F_ARR, (/N/))                                     

    PRINT *, F_ARR

END SUBROUTINE

但我不确定你是否需要拨打C_F_POINTER。以下作品也是如此:

SUBROUTINE SUBR(N, ARR) BIND(C)
    USE, INTRINSIC :: ISO_C_BINDING 
    IMPLICIT NONE

    INTEGER (C_INT), VALUE :: N
    REAL (C_FLOAT) :: ARR(N)

    PRINT *, ARR

END SUBROUTINE

(也许这是良好做法使用C_F_POINTER,我不知道。这是英特尔文档应该显示的内容:何时需要,何时不需要。)

编辑:在看了一下英特尔示例中的界面之后,我认为那里需要C_F_POINTER调用,因为该数组是C {{1}的一部分}。在声明struct时,您不能使成员数组具有可变长度,因此您必须将数据成员声明为TYPE并执行TYPE (C_PTR)例程。

所以这是将指针传递给清理结构的相同示例:

C_F_POINTER

这是从C调用的:

SUBROUTINE SUBR_STRUCT(OBJ) BIND(C)
    USE, INTRINSIC :: ISO_C_BINDING 
    IMPLICIT NONE

    TYPE, BIND(C) :: VECTOR 
        INTEGER (C_INT) :: LEN
        TYPE (C_PTR) :: DATA
    END TYPE VECTOR

    TYPE (VECTOR), INTENT(IN) :: OBJ
    REAL (C_FLOAT), POINTER :: ARR(:)

    CALL C_F_POINTER (OBJ%DATA, ARR, (/OBJ%LEN/))

    PRINT *, ARR

END SUBROUTINE

如果您提供struct obj { int len; float *data; }; extern void subr_struct(const struct obj *); int main(int argc, char **argv) { float data[] = {0.12, 0.15, 0.18, 0.23, 0.29}; struct obj o = {5, data}; subr_struct(&o); return 0; } OBJ属性,也可以按值传递结构。