通过ISO_C_绑定传递Fortran数组
我试图获得一个Fortran代码库,以便使用ISO_C_绑定调用C库调用,但在传递Fortran数组时遇到了问题 我创建了一个简单的例子来说明我的问题 main.f90通过ISO_C_绑定传递Fortran数组,c,arrays,fortran,fortran-iso-c-binding,C,Arrays,Fortran,Fortran Iso C Binding,我试图获得一个Fortran代码库,以便使用ISO_C_绑定调用C库调用,但在传递Fortran数组时遇到了问题 我创建了一个简单的例子来说明我的问题 main.f90 program main use iso_c_binding implicit none interface subroutine stuff(s,d) bind(c,name='doStuff') import :: c_char
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
职能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
字符被正确地传递,但是数组没有,我不知道如何更正它。我看到的例子表明要改变
double* w
到
但我不能这样做,因为我无法更改库代码以使其正常工作。我刚刚尝试创建一个新函数,将void*
强制转换为double*
,但没有效果:(。
同样,更改数组使其不可分配也是不可行的
想法?您对
d1的声明有问题。最好是
real(c_double), allocatable, target :: d1(:)
也就是说:它必须是正确的类型,才能与C的double进行互操作;要成为C_loc
的参数,它必须具有target
或pointer
属性
此外,正如Mahonri Moriancumer所指出的,您的printf
格式不适用于double。而且,可能值得考虑将stuff
作为一个函数而不是一个子程序。Timmy,在func.c
中,您的真正意思是:printf(“%f%f%f\n”,w[0],w[1],w[2],w[3]);
?(%d打印一个“int”值)信息性SO post:重要部分是real(c_double)
:对于ifort对c_loc
属性的漠不关心,我仍然感到惊讶。为什么这里需要target
属性?我使用target
属性进行了测试,代码仍然有效fine@SangjunLee,Fortran标准要求目标或指针属性(参见F2018 18.2.3.6)对于c_loc
的参数,尽管有些编译器(尤其是ifort)并不关心,而且似乎可以正常工作,但为了最大限度地提高正确性和可移植性,最好使用这些属性之一。
real(c_double), allocatable, target :: d1(:)