通常、Fortran コード と C コードの両方が含まれているプログラムでは、1 つの言語で記述されたルーチンから別の言語で記述されたルーチンを呼び出せることが望ましいでしょう。インテル® Fortran コンパイラーは Fortran 2003 規格をサポートしており、Fortran コードと C コードの確実な互換性を提供します。互換性保持のための型、変数、およびプロシージャーに関する条件を次に示します。
ISO_C_BINDING 組み込みモジュールには、組み込み型の種別型パラメーター値を保持する名前付き定数が含まれています。
一般的に使用される型を次の表に示します。次の条件が適用されます。
Fortran では、整数型は常に符号付きとします。C では、整数型は符号付きまたは符号なしとして指定される場合がありますが、デフォルトでは符号なしとします。
C_LONG、C_SIZE_T、C_LONG_DOUBLE、AND C_LONG_DOUBLE_COMPLEX の値は、プラットフォームにより異なります。
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);