I have tried to modify code from this this question到ISO_C_BINDING,但C_F_POINTER调用导致未定义的指针/数组(VS2010调试器)和print*, f_arr(i)
触发分段错误。我想我确实密切关注the array 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);
}
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编译器)
答案 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
属性,也可以按值传递结构。