C との互換性保持

通常、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 ポインターとの互換性保持

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;

Fortran からの C の呼び出し例

次の例は、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))
...

C からの Fortran の呼び出し例

次の例は、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);