9.5 C相互運用性 [主に5.1]
9.5.1 ISO_C_BINDING モジュール
組込みモジュールISO_C_BINDINGには次のものが含まれています。- それぞれのCの型(例えばfloat)に対し、対応するFortran型の種別パラメタ として使用可能な名前付き定数
- Cオブジェクトポインタと関数ポインタとの相互運用性を支援するC_PTR型と C_FUNPTR型
- FortranとCポインタを操作するための手続き
9.5.1.1 種別パラメタ
種別パラメタ名は対応するFortran型を利用するためのものです。例えば整数型に 対してはINTEGER、浮動小数点型に対してはREALがあります。 次の表はその対応を示したものです。 確実に利用可能なのはc_intのみである点に注意してください。もし対応する 型がない場合には値が負になります。
Cの型 | Fortranの型と種別 |
_Bool | LOGICAL(c_bool) |
char | CHARACTER(c_char) — For characters as text. |
double | REAL(c_double) |
double _Complex | COMPLEX(c_double_complex) or COMPLEX(c_double) |
float | REAL(c_float) |
float _Complex | COMPLEX(c_float_complex) or COMPLEX(c_float) |
int | INTEGER(c_int) |
int16_t | INTEGER(c_int16_t) |
int32_t | INTEGER(c_int32_t) |
int64_t | INTEGER(c_int64_t) |
int8_t | INTEGER(c_int8_t) |
int_fast16_t | INTEGER(c_int_fast16_t) |
int_fast32_t | INTEGER(c_int_fast32_t) |
int_fast64_t | INTEGER(c_int_fast64_t) |
int_fast8_t | INTEGER(c_int_fast8_t) |
int_least16_t | INTEGER(c_int_least16_t) |
int_least32_t | INTEGER(c_int_least32_t) |
int_least64_t | INTEGER(c_int_least64_t) |
int_least8_t | INTEGER(c_int_least8_t) |
intmax_t | INTEGER(c_intmax_t) |
intptr_t | INTEGER(c_intptr_t) |
long | INTEGER(c_long) |
long double | REAL(c_long_double) |
long double _Complex | COMPLEX(c_long_double_complex) or COMPLEX(c_long_double) |
long long | INTEGER(c_long_long) |
short | INTEGER(c_short) |
signed char | INTEGER(c_signed_char) — For characters as integers. |
size_t | INTEGER(c_size_t) |
9.5.1.2 C_PTRとC_FUNPTRの利用
これらは構造型名なのでType(c_ptr)とType(c_funptr)として使用できます。 Type(c_ptr)はCのvoid *とほぼ同等です。すなわちそれは任意のオブジェク トポインタを収容することができます。 Type(c_funptr)は関数ポインタについて同様の機能を提供します。Cの‘int *’のような引数の場合に、Type(c_ptr)を使う必要はあり ません。通常の仮引数(この場合Integer(c_int)型のもの)をVALUE属性 無しで使用できます。 しかしながらより複雑なポインタ引数(例えばポインタからポインタ)、あるいはポイン タである変数や成分に対しては、Type(c_ptr)を使用する必要があります。
Type(c_ptr)とType(c_funptr)のNullポインタ定数は共に提供されていま す。これらはそれぞれC_NULL_PTRとC_NULL_FUNPTRです。
Type(c_ptr)の値を作成する場合、関数C_LOC(X)をFortranオブジェクト Xに対して使用します(XはTARGET属性を持つ必要があります)。 またこの際のFortranオブジェクトは多相、ゼロの大きさの配列、大きさ引継ぎ配列、 配列ポインタであってはなりません。 Type(c_funptr)の値を作成する場合には、関数C_FUNLOCを手続きに対して 使用します。この手続きはBIND(C)属性を持っている必要があります。
Type(c_ptr)もしくはType(c_funptr)がヌルであるかどうかを調べるには C_ASSOCIATED(C_PTR_1)関数を用いることができます。 この関数はC_PTR_1がヌルでない場合に限り.TRUE.を返します。 2つのType(c_ptr)もしくは2つのType(c_funptr)の値は C_ASSOCIATED(C_PTR_1,C_PTR_2)関数を用いて比較できます。 これはC_PTR_1がC_PTR_2と同じCアドレスを持つ場合に限り.TRUE. を返します。
サブルーチンC_F_POINTER(CPTR,FPTR)はTYPE(C_PTR)の値CPTRを スカラのFortranポインタFPTRに変換します。 このFortranポインタは任意の型で構いませんが(相互運用性のない型を含む)、多相で あってはなりません。 サブルーチンC_F_POINTER(CPTR,FPTR,SHAPE)はTYPE(C_PTR)の値を Fortran配列ポインタFPTRに変換します。ここにSHAPEは1次元の整数配列 で、FPTRの次元数と同じ要素数を持つものです。結果となるFPTRの下限値 はすべて1です。
サブルーチンC_F_PROCPOINTER(CPTR,FPTR)が提供されています。これは TYPE(C_FUNPTR) CPTRをFortran手続きポインタFPTRに変換します。
これらすべての変換操作において、型や他の情報を正しく使うのはプログラマの責任で ある点に注意してください。
9.5.2 BIND(C)型
Cのstruct型に対応する構造型はその型をBIND(C)属性に与えることで 作成可能です。例:
TYPE,BIND(C) :: mytypeBIND(C)型の成分はCの型に対応する型を持っていなければならず、ポインタ もしくは割付けであってはなりません。 また、BIND(C)型はSEQUENCE型であってはなりません(それは既に SEQUENCE型であるかのような振舞いをします)。更に、型結合手続き や最終手続きを持っていてはならず、また拡張であってもなりません。
9.5.3 BIND(C)変数
Cのグローバル変数へのアクセスはFortran変数にBIND(C)属性を与える ことによって可能になります。 このような変数は一つのモジュール内でのみ宣言可能で、COMMON ブロック内では使用できません。 デフォルトではCの変数名はFortranの名前に変換されすべて小文字となります。 これと異なる名前を指定するにはNAME=節を利用します。例:
INTEGER,BIND(C,NAME="StrangelyCapiTalisedCName") :: xFortranコードの中において、変数はFortran名で参照され、C名で参照される わけではありません。
9.5.4 BIND(C)手続き
Cから呼び出すことができるFortranの手続きは、手続きの頭部分でBIND(C)属性を 指定して定義することができます。 デフォルトではFortran名を小文字に変換したC名が使用されます。異なる名前を 指定するにはNAME=節を利用します。例:
SUBROUTINE sub() BIND(C,NAME='Sub') ...繰り返しますがCの名前はCでのみ使用し、Fortranの名前はFortranでのみ使用します。 Cの名前がすべて空白もしくはゼロの長さを持つ文字列であった場合、Cの名前は存在 しません。このような手続きであっても手続きポインタを介して(つまり TYPE(C_FUNPTR)変数にその値を代入することによって)Cからコールすること が可能です。
BIND(C)手続きはモジュール手続きもしくは明示的な引用仕様を持つ外部手続きでなければなりません。 内部手続き及び文関数であってはなりません。
BIND(C)手続きはサブルーチン、もしくはCの型に対応する型を持ったスカラ 関数でも構いません。 それぞれの仮引数はC型に対応する型の変数でなくてはならず、割付け、形状引継ぎ、 省略可能、ポインタであってはなりません。 仮引数がVALUE属性を持たない場合には、ポインタであるC仮引数に対応する ことになります。
Fortran手続きとそれをCから参照する例を示します:
SUBROUTINE find_minmax(x,n,max,min) BIND(C,NAME='FindMinMax') USE iso_c_binding REAL(c_double) x(*),max,min INTEGER(c_int),VALUE :: n INTRINSIC maxval,minval max = MAXVAL(x(:n)) min = MINVAL(x(:n)) END extern void FindMinMax(double *x,int n,double *maxval,double *minval); double x[100],xmax,xmin; int n; ... FindMinMax(x,n,&xmax,&xmin);
これは、引用仕様ブロック内で呼ぶ出されるC手続きを記述することによって、Cの
手続きをFortranから呼び出すことも可能にします。
例を示します:
/* This is the prototype for a C library function from 4.3BSD. */ int getloadavg(double loadavg[],int nelem); PROGRAM show_loadavg USE iso_c_binding INTERFACE FUNCTION getloadavg(loadavg,nelem) BIND(C) IMPORT c_double,c_int REAL(c_double) loadavg(*) INTEGER(c_int),VALUE :: nelem INTEGER(c_int) getloadavg END FUNCTION END INTERFACE REAL(c_double) averages(3) IF (getloadavg(averages,3)/=3) THEN PRINT *,'Unexpected error' ELSE PRINT *,'Load averages:',averages END IF END
9.5.5 列挙
列挙は一群の同種の整定数を定義するもので、Cのenum宣言に相当します。例:
ENUM,BIND(C) ENUMERATOR :: open_door=4, close_door=17 ENUMERATOR :: lock_door END ENUMは次と等価です。
enum { open_door=4, close_door=17, lock_door };列挙子の一つに対して値が指定されなかった場合には、それは直前の値より1つ大きい 値(それが並びの中の最初の列挙子であった場合にはゼロ)を取ります。 特定の列挙子の集合に対して使われる種別は、KIND組込み関数を列挙子のいずれ かに対して用いることで見出すことができます。
BIND(C)節が必須である点に注意して下さい。標準はCとの相互運用を目的とした 列挙を規定しているに過ぎません。