2

我试图将这个问题的代码修改为 ISO_C_BINDING,但是 C_F_POINTER 调用会导致未定义的指针/数组(VS2010 调试器)并print*, f_arr(i)触发分段错误。我想我确实严格遵循数组 interop 的指示。

主程序

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);
}

子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 编译器)

4

1 回答 1

4

通过 Intel 文档中的 C 从 C 调用 Fortran 的示例ISO_C_BINDING不是很清楚。但在其他地方,我发现了这样的解释: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 的一部分struct。在声明您的 时TYPE,您不能将成员数组设为可变长度,因此您必须将数据成员声明为TYPE (C_PTR)并执行C_F_POINTER例程。

因此,这是将指针传递给已清理的结构的相同示例:

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

这是从 C 调用的,因此:

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,您也可以按值传递结构。VALUE

于 2014-01-28T11:25:30.037 回答