単一のデータ配列セットで動作する従来のFortran 90コードがあり、複数のデータセットを持つことができるようにコードを拡張したいと考えています。残念ながら、サブルーチンのどれも入力引数を取ることはなく、すべてのデータはモジュールを通して評価されます。以下のコードはFortranのコードと似ています。Cポインタを使用して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コードは、コードの変更少ない良好、(そこに約100の配列があり、すべての異なる形状およびサイズである)十分に複雑であるので。
割り当てられたFortran配列の場所を格納し、cポインタをモジュールに戻す2つの追加の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");
}
出力 - -
これら2つのサブルーチンで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
、我々は、Fortranコードを変更することなく、データのつ以上のコピー(次のコードでは10コピー)を持つことができます
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]
これにはまだ問題がありませんが、コンパイラ固有のさまざまな標準の実装に依存しているか、最近の標準との互換性により、これが機能しない可能性があります。レガシーFortran 90コードで共通の問題でなければならないことを処理するためのこのアプローチに関するコメントやフィードバックには、大変感謝しています。
'iso_c_binding'モジュールはFortran 2003まで標準化されていませんでした。 – francescalus
Fortran 90は完全に廃止されました。それは忘れて、Fortran 90に準拠する必要はありません。*最も重要な問題を修正した* Fortran 95を使用しますが、Fortran 2003または2008のほうが良いでしょう。 –