如何将 C_FLOAT 数组传递给 Fortran 子例程
Posted
技术标签:
【中文标题】如何将 C_FLOAT 数组传递给 Fortran 子例程【英文标题】:How to pass an array of C_FLOAT to a Fortran subroutine 【发布时间】:2018-01-15 20:17:18 【问题描述】:在 Fortran 中,我有一个 C_FLOAT
数组,它被声明为输入参数:
SUBROUTINE Main(n,myCArray) BIND(C, NAME = 'Main')
INTEGER(C_INT), INTENT(IN ) :: n
REAL(C_FLOAT), INTENT(INOUT), dimension(n) :: myCArray
CALL PrintTheArray(n,myCArray)
END SUBROUTINE MAIN
正如Main
子程序主体中所写,我想将myCArray
传递给另一个子程序,如下所示:
SUBROUTINE PrintTheArray(n,theCArray)
INTEGER(C_INT), INTENT(IN ) :: n
REAL(C_FLOAT), INTENT(INOUT), dimension(n) :: theCArray
print *, theCArray(1), theCArray(2)
END SUBROUTINE PrintTheArray
通过这样做,我从不打印数组的正确值。但是,如果我打印子程序Main()
中的值,则这些值是正确的。出了什么问题,我该如何解决?
在 Fortran 中传递 C_FLOAT
数组确实没有问题。所以这个问题是错误的。我在这里提供了一个最小、完整和可验证的示例(我使用 Ubuntu、GNU Fortran (GCC) 6.3.0、gcc (GCC) 6.3.0):
文件名为FORTRANFunc.f90
的Fortran代码
MODULE TEST
USE, INTRINSIC :: ISO_C_Binding
IMPLICIT NONE
contains
subroutine CALLFORTRAN(n,myArray) BIND (C, NAME = 'CALLFORTRAN')
INTEGER(C_INT), INTENT(IN ) :: n
REAL(C_FLOAT), INTENT(IN ) :: myArray(n)
CALL PRINTARRAY(n,myArray)
end subroutine CALLFORTRAN
subroutine PRINTARRAY(n, myArray)
INTEGER(C_INT), INTENT(IN ) :: n
REAL(C_FLOAT), INTENT(IN ) :: myArray(n)
print *, myArray(1), myArray(2)
end subroutine PRINTARRAY
END MODULE TEST
文件名为main.c
的C代码
#include <stdio.h>
#include <stdlib.h>
extern void CALLFORTRAN(int* n, float* myArray);
int main()
int n=2;
float* myArray = (float*) malloc(2);
myArray[0] = 0.5;
myArray[1] = 1.5;
CALLFORTRAN(&n,myArray);
return 0;
你可以编译:
gfortran -c FORTRANFunc.f90
gfortran main.c FORTRANFunc.o -o test
然后你执行:
./test
结果应该是:
0.500000000 1.50000000
【问题讨论】:
你能为我们创建一个minimal reproducible example 吗? 确实,当它没有打印正确的值时,它会打印什么?Main()
中的值是否正确?需要详细的问题说明和minimal reproducible example。
我感觉问题出在 C 代码上。通常,在 Fortran 子例程之间传递 C_FLOAT 数组是没有问题的。
第二行通常是USE ISO_C_BINDING。 C 是按引用传递还是按值传递?
@Holmz 如果上面的某个模块已经使用了use iso_c_binding
,那么它绝对没有理由。 use iso_c_binding
不会以任何方式更改调用约定(按值/引用传递)。
【参考方案1】:
我无法重现 gfortran 5.4.0(完整版:GNU Fortran (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
)或 IBM XL Fortran 的问题。可能是较新的 gfortran 有问题吗?
$ gfortran -c FORTRANFunc.f90
$ gcc -c main.c
$ gfortran FORTRANFunc.o main.o -o test
$ ./test
0.500000000 1.50000000
$
另外,将dimension(n)
更改为dimension(*)
有什么不同吗?
【讨论】:
其实这个问题是错误的,正如上面澄清的那样。所以在 FORTRAN 中传递 C_FLOAT 数组是完全可以的。把 dimension(n) 改成 dimension(*) 也是对的。以上是关于如何将 C_FLOAT 数组传递给 Fortran 子例程的主要内容,如果未能解决你的问题,请参考以下文章