【发布时间】:2017-05-30 19:10:19
【问题描述】:
我们有一个旧的 Fortran 90 代码,它对一组数据数组进行操作,并希望扩展代码以便我们可以拥有多组数据。不幸的是,没有一个子程序接受输入参数,而是通过模块评估所有数据。以下代码类似于我们的 Fortran 代码。
MODULE test_mod
IMPLICIT NONE
double precision, pointer :: f_x(:)
integer :: n = 5
END MODULE test_mod
SUBROUTINE alloc_x()
use test_mod
IMPLICIT NONE
allocate(f_x(n))
END SUBROUTINE alloc_x
SUBROUTINE init_x()
USE test_mod
IMPLICIT NONE
f_x = 1.0
END SUBROUTINE init_x
SUBROUTINE dealloc_x()
use test_mod
IMPLICIT NONE
deallocate(f_x)
END SUBROUTINE dealloc_x
由于 Fortran 代码足够复杂(大约有一百个数组,并且都具有不同的形状和大小),因此对代码的修改越少越好。我们提出了以下解决方案,并对该解决方案是否被视为与 Fortran 90 标准兼容感兴趣:
我们创建了两个额外的 Fortran 子例程,用于存储分配的 Fortran 数组的位置并将 c 指针复制回模块。
SUBROUTINE store_ptrs(c_x)
use iso_c_binding
use test_mod
IMPLICIT NONE
TYPE(c_ptr) :: c_x
c_x = c_loc(f_x)
END SUBROUTINE
SUBROUTINE copy_ptrs2mod(c_x)
use iso_c_binding
use test_mod
IMPLICIT NONE
TYPE(c_ptr) :: c_x
CALL c_f_pointer(c_x,f_x,[n])
END SUBROUTINE
通过这两个子程序,我们可以拥有多于一份的数据(以下代码中为 10 份),而无需更改 Fortran 代码 --
#include <stdio.h>
#include <stdlib.h>
void alloc_x_();
void init_x_();
void dealloc_x_();
void store_ptrs_(double **c_x);
void copy_ptrs2mod_(double **c_x);
void output_result(int entry, double* array);
int main()
{
int i;
double *x[10];
/* allocate array */
for(i=0; i<10; i++){
alloc_x_();
store_ptrs_(&x[i]);
}
/* initialize array */
for(i=0; i<10; i++){
copy_ptrs2mod_(&x[i]);
init_x_();
output_result(i,x[i]);
}
/* deallocate the array */
for(i=0; i<10; i++){
copy_ptrs2mod_(&x[i]);
dealloc_x_();
}
}
void output_result(int entry, double* array){
int j;
printf("x[%2d] = [", entry);
for (j = 0; j < 5; ++j)
{
if (j == 4)
{
printf("%3.1f",array[j]);
continue;
}
printf("%3.1f, ",array[j]);
}
printf("]\n");
}
输出 -
x[ 0] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 1] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 2] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 3] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 4] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 5] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 6] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 7] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 8] = [1.0, 1.0, 1.0, 1.0, 1.0]
x[ 9] = [1.0, 1.0, 1.0, 1.0, 1.0]
虽然我们还没有看到这方面的任何问题,但我们有点担心我们可能(隐式地)依赖于各种标准的编译器特定实现,或者与最新标准的其他一些不兼容可能会阻止它工作。我们非常感谢任何有关此方法的 cmets 或反馈,以处理传统 Fortran 90 代码的常见问题。
【问题讨论】:
-
模块
iso_c_binding直到 Fortran 2003 才标准化。 -
Fortran 90 已完全过时。算了,不需要 Fortran 90 合规性。 至少使用解决了最大问题的 Fortran 95,但使用 Fortran 2003 或 2008 更好。
标签: fortran