通常、Fortran コード と C コードの両方が含まれているプログラムでは、1 つの言語で記述されたルーチンから別の言語で記述されたルーチンを呼び出せることが望ましいでしょう。インテル(R) Fortran コンパイラーは Fortran 2003 規格をサポートしており、Fortran コードと C コードの確実な互換性を提供します。互換性保持のための型、変数、およびプロシージャーに関する条件を次に示します。
ISO_C_BINDING 組み込みモジュールには、組み込み型の種別型パラメーター値を保持する名前付き定数が含まれています。
一般的に使用される型を次の表に示します。次の条件が適用されます。
ISO_C_BINDING の名前付き定数 (正の値の場合は種別型パラメーター) |
C のデータ型 | 相当する Fortran のデータ型 |
C_SHORT C_INT C_LONG C_LONG_LONG |
short int int long int long long int |
INTEGER(KIND=2) INTEGER(KIND=4) INTEGER (KIND=4 または 8) INTEGER(KIND=8) |
C_SIGNED_CHAR | signed char unsigned char |
INTEGER(KIND=1) |
C_SIZE_T | size_t | INTEGER(KIND=4 または 8) |
C_INT8_T C_INT16_T C_INT32_T C_INT64_T |
int8_t int16_t int32_t int64_t |
INTEGER(KIND=1) INTEGER(KIND=2) INTEGER(KIND=4) INTEGER(KIND=8) |
C_FLOAT C_DOUBLE C_LONG_DOUBLE |
float double long double |
REAL(KIND=4) REAL(KIND=8) REAL(KIND=8 または 16) |
C_FLOAT_COMPLEX C_DOUBLE_COMPLEX C_LONG_DOUBLE_COMPLEX |
float _Complex double _Complex long double _Complex |
COMPLEX(KIND=4) COMPLEX(KIND=8) COMPLEX(KIND=8 または 16) |
C_BOOL | _Bool | LOGICAL(KIND=1) |
C_CHAR | char | CHARACTER(LEN=1) |
すべての C のデータ型に対して名前付き定数がありますが、各プロセッサーですべてのデータ型がサポートされているわけではありません。モジュールの定数が負の値の場合は、そのデータ型はサポートされていません。
char 型の互換性を保持するためには、文字長を省略するか、または値が 1 の初期値式を使用して指定する必要があります。
C ポインターとの互換性を保持するために、ISO_C_BINDING モジュールには、C のオブジェクト・ポインターおよび関数ポインターと互換性のある、派生型 C_PTR と C_FUNPTR が含まれています。
これらの型およびモジュールの特定のプロシージャーは、2 つの言語間で動的配列を渡すためのメカニズムを提供します。動的配列の要素は、メモリー内で連続して格納する必要がないため、Fortran ポインターのターゲットまたは形状引継ぎ配列を C へ渡すことはできません。ただし、すでに割り付けられている割付け配列を C へ渡したり、C で割り付けられた配列を Fortran ポインターに関連付けることはできます。
派生型と C の互換性を保持するためには、次のように、BIND(C) 属性を指定する必要があります。
TYPE, BIND(C) :: MYTYPE
さらに、次の例のように、各コンポーネントで互換性のある型と型パラメーター (ポインターではなく、割り当て可能でもない) を使用する必要があります。これにより、Fortran のデータ型と C のデータ型を対応させることができます。
typedef struct {
int m, n;
float r;
} myctype
上記のコードに対応する Fortran コードは次のとおりです。
USE, INTRINSIC :: ISO_C_BINDING
TYPE, BIND(C) :: MYFTYPE
INTEGER(C_INT) :: I, J
REAL(C_FLOAT) :: S
END TYPE MYFTYPE
Fortran スカラー変数は、型および型パラメーターに互換性があり、ポインターではない場合、互換性があります。
Fortran 配列変数は、型および型パラメーターに互換性があり、明示形状配列または大きさ引き継ぎ配列の場合、互換性があります。また、型、型パラメーター、および形状が同じで、添字が逆の C 配列とも互換性があります。
例えば、INTEGER :: A(18, 3:7, *) と宣言された Fortran 配列は、int b[][5][18] と宣言された C 配列と互換性があります。
プロシージャーの互換性を保持するためには、次のように、明示的なインターフェイスを使用し、BIND 属性で宣言する必要があります。
FUNCTION FUNC(I, J, K, L, M), BIND(C)
関数の場合、その結果はスカラーで、互換性がなければなりません。
プロシージャーには、グローバルなバインディング・ラベルが関連付けられています。このラベルは、C プロセッサーで認識される名前です。デフォルトでは、Fortran の名前をすべて小文字にしたものです。例えば、上記の関数のバインディング・ラベルは func です。次のように、別のバインディング・ラベルを指定することもできます。
FUNCTION FUNC(I, J, K, L, M), BIND(C, NAME=’myC_Func’)
すべての仮引数に互換性がなければなりません。さらに、Fortran ルーチンでスカラー仮引数に VALUE 属性が使用されているか、C ルーチンでこれらのスカラー引数をスカラー値へのポインターとして受け取っていなければなりません。次の C 関数の呼び出しについて考えてみます。
intc_func(int x, int *y);
ここで示すように、Fortran から c_func を呼び出すためのインターフェイスでは、x は VALUE 属性で渡す必要がありますが、y はポインターとして受け取られるため、VALUE 属性を使用することはできません。
INTERFACE
INTEGER (C_INT) FUNCTION C_FUNC(X, Y) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
INTEGER (C_INT), VALUE :: X
INTEGER (C_INT) :: Y
END FUNCTION C_FUNC
END INTERFACE
別の方法として、y を値によって渡される C_PTR として宣言することもできます。
TYPE (C_PTR), VALUE :: Y
char 型の Fortran スカラー変数を渡す場合、文字長は 1 でなければなりません。
モジュール変数または共通ブロックは、Fortran のエンティティーで BIND 属性を使用していて、そのメンバーも互換性がある場合、C グローバル変数と互換性があります。例えば、次のモジュールの C_EXTERN、C2、COM および SINGLE について考えてみます。
MODULE LINK_TO_C_VARS
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT), BIND(C) :: C_EXTERN
INTEGER(C_LONG) :: C2
BIND(C, NAME=’myVariable’) :: C2
COMMON /COM/ R,S
REAL(C_FLOAT) :: R,S,T
BIND(C) :: /COM/, /SINGLE/
COMMON /SINGLE/ T
END MODULE LINK_TO_C_VARS
これらは、次の C 外部変数と互換性があります。
int c_extern;
long myVariable;
struct {float r, s;} com;
float single;
次の例は、C 関数を呼び出します。
C の関数プロトタイプ:
int C_Library_Function(void* sendbuf, int sendcount, int *recvcounts);
Fortran のモジュール:
MODULE FTN_C_1
USE, INTRINSIC :: ISO_C_BINDING
END MODULE FTN_C_1
MODULE FTN_C_2
INTERFACE
INTEGER (C_INT) FUNCTION C_LIBRARY_FUNCTION &
(SENDBUF, SENDCOUNT, RECVCOUNTS) &
BIND(C, NAME=’C_Library_Function’)
USE FTN_C_1
IMPLICIT NONE
TYPE (C_PTR), VALUE :: SENDBUF
INTEGER (C_INT), VALUE :: SENDCOUNT
TYPE (C_PTR), VALUE :: RECVCOUNTS
END FUNCTION C_LIBRARY_FUNCTION
END INTERFACE
END MODULE FTN_C_2
Fortran の呼び出しシーケンス:
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT, C_FLOAT, C_LOC
USE FTN_C_2
...
REAL (C_FLOAT), TARGET :: SEND(100)
INTEGER (C_INT) :: SENDCOUNT
INTEGER (C_INT), ALLOCATABLE, TARGET :: RECVCOUNTS(100)
...
ALLOCATE( RECVCOUNTS(100) )
...
CALL C_LIBRARY_FUNCTION(C_LOC(SEND), SENDCOUNT, &
C_LOC(RECVCOUNTS))
...
次の例は、SIMULATION という Fortran のサブルーチンを呼び出します。このサブルーチンは、C の void simulation 関数に対応します。
Fortran のコード:
SUBROUTINE SIMULATION(ALPHA, BETA, GAMMA, DELTA, ARRAYS) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
INTEGER (C_LONG), VALUE :: ALPHA
REAL (C_DOUBLE), INTENT(INOUT) :: BETA
INTEGER (C_LONG), INTENT(OUT) :: GAMMA
REAL (C_DOUBLE),DIMENSION(*),INTENT(IN) :: DELTA
TYPE, BIND(C) :: PASS
INTEGER (C_INT) :: LENC, LENF
TYPE (C_PTR) :: C, F
END TYPE PASS
TYPE (PASS), INTENT(INOUT) :: ARRAYS
REAL (C_FLOAT), ALLOCATABLE, TARGET, SAVE :: ETA(:)
REAL (C_FLOAT), POINTER :: C_ARRAY(:)
...
!Associate C_ARRAY with an array allocated in C
CALL C_F_POINTER (ARRAYS%C, C_ARRAY, (/ARRAYS%LENC/) )
...
!Allocate an array and make it available in C
ARRAYS%LENF = 100
ALLOCATE (ETA(ARRAYS%LENF))
ARRAYS%F = C_LOC(ETA)
...
END SUBROUTINE SIMULATION
C の構造体宣言:
struct pass {int lenc, lenf; float *c, *f;};
C の関数プロトタイプ:
void simulation(long alpha, double *beta, long *gamma, double delta[], struct pass *arrays);
C の呼び出しシーケンス:
simulation(alpha, &beta, &gamma, delta, &arrays);