C との互換性保持

通常、Fortran コード と C コードの両方が含まれているプログラムでは、1 つの言語で記述されたルーチンから別の言語で記述されたルーチンを呼び出せることが望ましいでしょう。インテル® 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);