从C向Fortran子例程传递未知长度数组失败,如何无长度指定传递?
Fortran与C交互:动态传递数组无需指定固定长度的解决方案
问题背景
你编写的Fortran子例程通过bind(c)与C主程序交互,当使用假定形状数组(integer(c_int) a(:))时,打印数组会失败;但将数组声明改为固定长度(a(5))则能正常运行。核心需求是实现无需硬编码数组长度,即可在Fortran中正确处理来自C的数组。
根本原因
C语言仅传递数组的首地址,不会附带数组的长度、形状等元数据;而Fortran的假定形状数组依赖内部的*描述符(descriptor)*来解析数组结构,缺少这个描述符时,Fortran无法正确识别数组的边界,进而导致运行错误。固定长度数组不需要描述符,直接按首地址+固定长度访问内存,因此可以正常工作。
可行解决方案
1. 显式传递数组长度(最直接可靠的方式)
在C调用时额外传递数组长度,Fortran子例程用该长度定义显式形状数组,即可正常操作数组。
修改后的Fortran子例程:
subroutine my_subroutine(a, b, arr_len) bind(c, name='my_subroutine') use iso_c_binding implicit none integer(c_int), intent(in) :: arr_len integer(c_int), intent(in) :: a(arr_len) real(c_double), intent(in) :: b(arr_len) print *, "Printing from Fortran subroutine:" print *, "Array a content:" print *, a print *, "Array b content:" print *, b end subroutine my_subroutine
对应的C主程序:
#include <stdlib.h> void my_subroutine(int *, double *, int); int main() { const int arr_len = 5; int *a = calloc(arr_len, sizeof(int)); double *b = calloc(arr_len, sizeof(double)); for (int i = 0; i < arr_len; i++) { a[i] = i; b[i] = i; } my_subroutine(a, b, arr_len); free(a); free(b); return EXIT_SUCCESS; }
2. 使用c_ptr与c_f_pointer转换(灵活处理动态数组)
先接收C传递的指针,再通过Fortran的c_f_pointer函数将其关联到假定形状数组,同样需要传递数组长度来指定形状。
Fortran子例程示例:
subroutine my_subroutine(a_ptr, b_ptr, arr_len) bind(c, name='my_subroutine') use iso_c_binding implicit none type(c_ptr), intent(in) :: a_ptr, b_ptr integer(c_int), intent(in) :: arr_len integer(c_int), pointer :: a(:) real(c_double), pointer :: b(:) ! 将C指针关联到Fortran假定形状数组 call c_f_pointer(a_ptr, a, [arr_len]) call c_f_pointer(b_ptr, b, [arr_len]) print *, "Printing from Fortran subroutine:" print *, a print *, b end subroutine my_subroutine
C主程序修改与第一种方法一致,需传递arr_len参数。
3. 假定大小数组(不推荐,仅兼容旧代码)
可以用integer(c_int) a(*)声明假定大小数组,此时Fortran不检查数组边界,但打印整个数组仍需知道长度,且存在越界访问风险,不建议在新代码中使用。
内容的提问来源于stack exchange,提问作者DJames
相关产品推荐
相关产品推荐

