我可以在 Fortran(77 标准)中创建和使用动态二维数组。现在,我想在 Fortran 程序的 C 函数中创建我的动态二维数组(使用我们说的“malloc”),并能够通过 Fortran 程序访问它。在 Fortran 中,我还希望能够像 a(1:n,2) 或 a(1,2) 那样做某事,并且还能够从 Fortran 子例程中传递和检索我的数组。请你给我举个例子,花点时间解释一下(如果可能的话,我真的很感激)记忆将如何排列?万分感谢!此外,如果二维不能直接工作,我可以在 C 函数中创建一维数组,但是从 Fortran 访问它,因为它是一个二维数组......谢谢!
3 回答
最重要的区别是索引顺序。Fortran 使用数学符号,因此第一个索引是列索引,第二个索引是行。C 不同,第一个索引是行。
宏解释了这一点
#define AccessFortranArray(ArrayName, i,j) ArrayName[j][i]
要在 C 中执行 a(1:n, 2) 之类的操作,只能创建临时数组并在循环中提取元素(不包括要提取一系列行的情况 - 在这种情况下,您可以在 C 中使用指针算术)
C <-> Fortran 互操作有很好的参考,比如这个
这里还有一个多维样本:Passing Array To/From Fortran
“还有一件事”。
C 函数的名称必须在末尾包含下划线才能在 Fortran 中可见。它们也必须是小写的。这都是指 gcc/gfortran 对。
还有一个。你已经告诉过你能够传递数组,所以你知道(Jim Balter 在评论中说)Fortran 数组是基于 1 的,而 C 数组是基于 0 的。
第三个。如果您只需要一大块数据,那么不要弄乱链接设置和函数调用约定,而是使用 COMMON 块。
像这样
/* C Code */
extern struct
{
double arr[100];
} thearr_;
和 Fortran:
real*8 arr(100)
common/TheArr/ arr
不,您不能在 FORTRAN 77 标准中创建动态数组。
您也不能使用 malloc 创建 Fortran“动态”数组,任何尝试从 Fortran 释放它都会导致崩溃。(您当然可以以正常方式将其用作静态数组。)
此外,如果您明确要求 FORTRAN 77,请不要使用像 a(1:n,2) 这样的符号。本标准不支持。
在 Fortran 2003 中有iso_c_binding,但在 FORTRAN 77 中不存在类似的东西,您只能传递假定大小的数组并处理编译器使用的任何名称修改(即来自 C 的 Fotran 过程名称中的尾随下划线)。
为什么你必须在 FORTRAN 77 中做这些事情?它们在 Fortran 2003 或带有 ISO C 绑定的 Fortran 95 中要容易得多。几乎所有当前 Fortran 95 级别的 Fortran 编译器都带有 ISO C 绑定。该组合提供了您想要的功能,作为语言标准的一部分,因此以独立于平台和编译器的方式。
如果您只需要创建动态数组,您可以直接在 Fortran 95 中使用可分配数组来完成。如果您有不想更改的 FORTRAN 77 代码,您可以编写一些 Fortran 95 代码并将两者混合。您可以将在 Fortran 95 中创建的可分配数组传递给另一个未将其声明为可分配的 Fortran 过程。
如果出于某种原因需要在 C 中创建数组,您可以使用 ISO C 绑定来描述 Fortran 中的 C 例程。在 C 中使用 malloc 创建的数组以 Fortran 类型 C_PTR 传递给 Fortran。然后使用 Fortran 内部子例程 c_f_pointer 将该存储连接到 Fortran 数组。之后使用 Fortran 数组,它与 Fortran 数组相同。
确实,多维数组的索引顺序在语言之间是不同的。这是因为 Fortran 是一种列优先语言,而 C 是一种行优先语言。但是,Fortran 数组不必是一个索引。这只是默认设置。您可以更改声明中的起始索引:实数数组 (0:99)。或者对于带有指针边界重新分配的 c_f_pointer 的指针数组设置:array (0:99) => array