XL Fortran for AIX V8.1.1

ユーザーズ・ガイド


言語から別の言語にデータを渡す

次の表は、XL Fortran、Pascal および C 言語で使用可能なデータ型を示しています。

言語間での引き数の引き渡し


表 24. Fortran、C、および Pascal において対応するデータ型

C のルーチンと Pascal のルーチンは、Fortran を呼び出す時、この表にリストされているタイプに対するポインターとして引き数を渡す必要があります。
XL Fortran データ型 IBM C データ型 XL Pascal データ型
INTEGER(1) BYTE signed char PACKED -128..127
INTEGER(2) signed short PACKED -32768..32767
INTEGER(4) signed int INTEGER
INTEGER(8) signed long long (注 1 を参照) --
REAL REAL(4) float SHORTREAL
REAL(8) DOUBLE PRECISION double REAL
REAL(16) long double (注 2 を参照) --
COMPLEX COMPLEX(4) 2 つの float の構造体 2 つの SHORTREAL のレコード
COMPLEX(8) DOUBLE COMPLEX 2 つの double の構造体 2 つの REAL のレコード
COMPLEX(16) 2 つの long double の構造体 --
LOGICAL(1) unsigned char PACKED 0..255
LOGICAL(2) unsigned short PACKED 0..65535
LOGICAL(4) unsigned int --
LOGICAL(8) unsigned long long (注 1 を参照) --
CHARACTER char CHAR
CHARACTER(n) char[n] PACKED ARRAY[1..n] OF CHAR
Integer POINTER void * POINTER、または @INTEGER などの型付きポインター (注 3 を参照)
Array array ARRAY
シーケンス派生型 構造体 (C -qalign=packed オプション付き) PACKED RECORD

注:

  1. XL C では -qlanglvl=extended オプション、C for AIX および C Set ++ for AIX では -qlonglong オプションが必要です。これらは一部のコンパイル・コマンドではデフォルトのオプションですが、そうでないコマンドもあります。
  2. C コンパイラーの -qlongdbl オプションが必要です。
  3. XL Pascal の -qptr4 オプションが必要です。

注:

  1. 言語間通信では、参照または値による引き数の引き渡しで定義された %VAL および %REF 組み込み関数を使用しなければならないことがあります。

  2. プロトタイプ化されていない C 関数を呼び出す時に、C プログラムは浮動小数点値を倍精度へ、および短精度整数値へと自動的に変換します。 XL Fortran は、値によって引き渡された REAL(4) の数量に対して変換を実行しないので、関数プロトタイプで宣言していない C 関数の引き数として REAL(4) 値と INTEGER(2) 値を渡さないでください。

  3. |Fortran 派生型、Pascal RECORD、および C の構造体が、 |互換データ型であるためには、サブオブジェクトの数、データ型、 |および長さが一致している必要があります。
関連情報:
ディレクトリー /usr/lpp/xlf/samples の 1 つまたは複数のサンプル・プログラムは、Fortran から C への呼び出し方法を説明しています。

言語間でのグローバル変数の引き渡し

Fortran プログラム内から C データ構造にアクセスする場合、あるいは C プログラム内から共通ブロックにアクセスする場合は、次のようにします。

  1. C 構造体メンバーの 1 対 1 マッピングを提供する名前付き共通ブロックを作成します。名前なし共通ブロックがある場合は、名前付き共通ブロックに変更します。その共通ブロックには、C 構造体の名前を付けます。
  2. C 構造体をグローバル変数として宣言します。宣言は、関数の外に置くか、extern 修飾子を持つ関数内に置きます。
  3. -qalign=packed を指定して C ソース・ファイルをコンパイルします。

 program cstruct                         struct mystuff {
 real(8) a,d                                    double a;
 integer b,c                                    int b,c;
 .                                              double d;
 .                                       };
 common /mystuff/ a,b,c,d
 .                                       main() {
 .
 end                                     }

名前付き共通ブロックを特に必要としない場合は、C 構造体と同じ 1 対 1 マッピングを指定してシーケンス派生型を作成し、 C 関数に引き数として渡すことができます。 -qalign=packed を指定して C ソース・ファイルをコンパイルする必要があります。

|THREADLOCAL と宣言された共通ブロックは、 |コンパイラー生成コードにより動的に割り振られる、 |スレッド固有のデータ域です。 |静的ブロックは THREADLOCAL 共通ブロック用に予約済みのままですが、 |コンパイラーおよびコンパイラーの実行時環境が制御情報用にそれを使用します。 |THREADLOCAL 共通ブロックを Fortran と C プロシージャーとの間で共用する必要がある場合、 |C ソースには THREADLOCAL 共通ブロックのインプリメンテーションを知らせておく必要があります。 |詳細については、「XL Fortran for AIX ランゲージ・リファレンス 」の |ディレクティブ 』の章にある |THREADLOCAL 共通ブロック、 |および 付録 A, サンプルの Fortran プログラムを参照してください。

|THREADPRIVATE と宣言されている共通ブロックへの |アクセスは、C for AIX 4.5 以降を使用して、THREADPRIVATE として |宣言されている C グローバル変数を使用して行うことができます。

言語間の文字タイプの引き渡し

言語間呼び出しの難しい面の 1 つは、言語間でストリングを引き渡すことです。これが難しいのは、以下に示すように、複数の異なる言語がそのようなエンティティーを表す方法が異なるためです。

混合言語プログラムとして両方の部分を作成している場合、C ルーチンに追加の Fortran 長さ引き数を処理させるようにすることもできますし、 %REF 関数を使用してストリングを渡すことによってこの追加引き数を抑止することもできます。 %REF (通常はあらかじめ存在している C ルーチン用) を使用すると、 C ルーチンに渡される個々のストリングの終わりにヌルを連結して、どこでストリングが終わるかを示す必要があります。

! Initialize a character string to pass to C.
               character*6 message1 /'Hello\0'/
! Initialize a character string as usual, and append the null later.
               character*5 message2 /'world'/
 
! Pass both strings to a C function that takes 2 (char *) arguments.
               call cfunc(%ref(message1), %ref(message2 // '\0'))
               end

C 言語との互換性を得るために、XL Fortran ストリングで以下のエスケープ・シーケンスをエンコードすることができます。

表 25. ストリングのエスケープ・シーケンス

エスケープ 意味
\b バックスペース
\f 書式送り
\n 改行
\t タブ
\0 ヌル
\' アポストロフィ (ストリングは終了しません)
\" 二重引用符 (ストリングは終了しません)
\ \ バックスラッシュ
\x x。ここで x は任意の文字 (バックスラッシュは無視されます)

ストリング内でバックスラッシュをエスケープ・シーケンスとして解釈させたくない場合は、 -qnoescape オプションを指定してコンパイルすることができます。

言語間での配列の引き渡し

Fortran は、配列エレメントを列順で記憶単位に保管します。 C および Pascal は、行順に配列エレメントを保管します。 Fortran および Pascal 配列指標は 1 から開始しますが、C 配列指標は 0 から開始します。

以下の例は、Fortran、C、および Pascal で A(3,2) によって宣言された 2 次元の配列がどのように保管されるかを示しています。

表 26. Fortran、C、Pascal の対応する配列レイアウト

Fortran の配列参照 A(X,Y,Z) は、C では a[Z-1][Y-1][X-1] で表現し、 Pascal では A[Z,Y,X] で表現します。 C では個々のスカラー配列エレメントは値によって渡しますが、配列は参照によって渡すことに注意してください。
  Fortran エレメント名 C エレメント名 Pascal エレメント名
一番低い記憶単位 A(1,1) A[0][0] A[1,1]
  A(2,1) A[0][1] A[1,2]
  A(3,1) A[1][0] A[2,1]
  A(1,2) A[1][1] A[2,2]
  A(2,2) A[2][0] A[3,1]
一番高い記憶単位 A(3,2) A[2][1] A[3,2]

Fortran 配列のすべてまたは一部を他の言語に渡すには、 Fortran 90 または Fortran 95 配列表記を使用することができます。

REAL, DIMENSION(4,8) :: A, B(10)
 
! Pass an entire 4 x 8 array.
CALL CFUNC( A )
! Pass only the upper-left quadrant of the array.
CALL CFUNC( A(1:2,1:4) )
! Pass an array consisting of every third element of A.
CALL CFUNC( A(1:4:3,1:8) )
! Pass a 1-dimensional array consisting of elements 1, 2, and 4 of B.
CALL CFUNC( B( (/1,2,4/) ) )

必要な場合には、Fortran プログラムは一時配列を作成して、すべてのエレメントを連続するストレージにコピーします。あらゆる場合に、C ルーチンは配列の列順レイアウトを考慮に入れる必要があります。

配列セクションまたは不連続配列は、対応する仮引き数が形状引き継ぎ配列またはポインターとして宣言される場所に明示インターフェースが存在しないと、連続する一時アドレスとして渡されます。配列引き数で Fortran 以外のプロシージャーを呼び出す時に、配列記述子 (言語間呼び出しに対してサポートされていない) の作成を回避するために、Fortran 以外のプロシージャーに明示インターフェースを与えたり、インターフェースの形状引き継ぎ配列またはポインターとして、対応する仮引き数を宣言しないでください。

! This explicit interface must be changed before the C function
! can be called.
INTERFACE
  FUNCTION CFUNC (ARRAY, PTR1, PTR2)
    INTEGER, DIMENSION (:) :: ARRAY          ! Change this : to *.
    INTEGER, POINTER, DIMENSION (:) :: PTR1  ! Change this : to *
                                             ! and remove the POINTER
                                             ! attribute.
    REAL, POINTER :: PTR2                    ! Remove this POINTER
                                             ! attribute or change to TARGET.
  END FUNCTION
END INTERFACE

言語間のポインターの引き渡し

整数 POINTER は、常にポインター先オブジェクトのアドレスを表し、次のように、必ず値によって渡す必要があります。

CALL CFUNC(%VAL(INTPTR))

XL Fortran バージョン 2 からの FORTRAN 77 POINTER 拡張機能は、 Fortran 90 での POINTER と意味を区別するため、現在は 『整数 POINTER』 と呼ばれていることに注意してください。

Fortran 90 POINTER は、言語間でやりとりすることはできますが、これは呼び出されたプロシージャーに対して明示インターフェースが存在しない場合にのみ、あるいは、明示インターフェース内の引き数が POINTER 属性または形状引き継ぎ宣言子を持っていない場合に限られます。 POINTER 属性を除去したり、TARGET に変更したり、さらに形状無指定配列の配列宣言子があれば、形状明示型または大きさ引き継ぎに変更することができます。

XL Fortran では参照によって呼び出すという規則があるので、他言語のスカラー値であっても、値そのものではなく値のアドレスとして渡す必要があります。たとえば、整数値 x を Fortran へ渡す C 関数は &x を渡す必要があります。さらに、ポインター値 p を整数 POINTER として使用できるように Fortran に渡す C 関数はその値を void **p として宣言する必要があります。C の配列は例外で、& 演算子なしで Fortran に渡すことができます。

参照または値による引き数の引き渡し

Fortran 以外の言語で書かれたサブプログラム (たとえば、ユーザー作成 C プログラム、|オペレーティング・システム・ルーチンなど) を呼び出すためには、Fortran が使用するデフォルトの方式とは異なる方式で実引き数を渡さなければならない場合があります。 C ルーチン (libc.a などのようなシステム・ライブラリー内の C ルーチンも含む) は、引き数を参照によって渡すのではなく、値によって渡す必要があります。 (C は、個々のスカラー配列エレメントを値によって渡しますが、配列は参照によって渡します。)

デフォルトの引き渡し方法は、CALL ステートメントまたは関数参照の引き数リスト内で組み込み関数 %VAL および %REF を使用して変更することができます。これらの組み込み関数を、Fortran プロシージャー参照の引き数リストまたは選択戻り指定子で使用することはできません。

%REF
参照によって引き数を渡します (つまり、呼び出されたサブプログラムは引き数のアドレスを受け取ります)。これは、ストリングに対して余分な長さ引き数の抑止も行うということを除き、 Fortran のデフォルト呼び出し方式と同じです。

%VAL
値によって引き数を渡します (つまり、呼び出されたサブプログラムは、実引き数と同じ値を持つ引き数を受け取りますが、この引き数に対して加えられた変更は、実引き数には影響しません)。

この組み込み関数は、タイプが CHARACTER(1) 式、 BYTE 式、論理式、整数式、実数式、複素数式、またはシーケンス派生型のいずれかである実引き数で使用することができます。派生型のオブジェクトに、ポインター、配列、または長さが 1 バイトよりも長い文字構造体コンポーネントを入れることはできません。

%VAL は、長さが 1 バイトよりも長い配列エンティティー、プロシージャー名、文字式である実引き数で使用することはできません。

%VAL を使用すると、XL Fortran は実引き数を 32 ビットまたは 64 ビットの中間値として渡します。

32 ビット・モード

実引き数が、次のいずれかである場合:

  • 32 ビットより短い整数値または論理値の場合は、符号付きの 32 ビット値に拡張されます。
  • 32 ビットよりも長い整数値または論理値の場合は、2 つの 32 ビットを介在した値になります。
  • 実数式または複素数式の場合は、複数の 64 ビットを介在した値として渡されます。
  • シーケンス派生型の場合は、複数の 32 ビットを介在した値として渡されます。

バイト名付き定数および変数は、INTEGER(1) であるかのように渡されます。実引き数が CHARACTER(1) の場合は、 -qctyplss コンパイラー・オプションを指定したかどうかに関係なく、 32 ビット値になるまでコンパイラーが左側にゼロを埋め込みます。

64 ビット・モード

実引き数が、次のいずれかである場合:

  • 64 ビットより短い整数値または論理値の場合は、符号付きの 64 ビット値に拡張されます。
  • 実数式または複素数式の場合は、複数の 64 ビットを介在した値として渡されます。
  • シーケンス派生型の場合は、複数の 64 ビットを介在した値として渡されます。

バイト名付き定数および変数は、INTEGER(1) であるかのように渡されます。実引き数が CHARACTER(1) の場合は、 -qctyplss コンパイラー・オプションを指定したかどうかに関係なく、 64 ビット値になるまでコンパイラーが左側にゼロを埋め込みます。

-qautodbl コンパイラー・オプションを指定した場合、埋め込まれたストレージは、派生型のオブジェクト以外は渡されません。

  EXTERNAL FUNC
  COMPLEX XVAR
  IVARB=6
 
  CALL RIGHT2(%REF(FUNC))       ! procedure name passed by reference
  CALL RIGHT3(%VAL(XVAR))       ! complex argument passed by value
  CALL TPROG(%VAL(IVARB))       ! integer argument passed by value
  END

%VAL および %REF 用の明示インターフェース

Fortran 以外のプロシージャーに対して明示インターフェースを以下のよう指定して、個々の引き数リスト内の %VAL および %REF への呼び出しのコーディングを回避することができます。

INTERFACE
    FUNCTION C_FUNC(%VAL(A),%VAL(B)) ! Now you can code "c_func(a,b)"
        INTEGER A,B                  ! instead of
    END FUNCTION C_FUNC              ! "c_func(%val(a),%val(b))".
END INTERFACE

Fortran 関数からの値の戻り

XL Fortran は、Fortran 以外のプロシージャーからのある種の呼び出しをサポートしていません。 Fortran 関数がポインター、配列、または不定長の文字を戻す場合は、 Fortran 以外からその関数を呼び出さないでください。

以下のような関数を間接的に呼び出すことはできます。

SUBROUTINE MAT2(A,B,C)    ! You can call this subroutine from C, and the
                          ! result is stored in C.
INTEGER, DIMENSION(10,10) :: A,B,C
C = ARRAY_FUNC(A,B)       ! But you could not call ARRAY_FUNC directly.
END

OPTIONAL 属性を持つ引き数

オプションの引き数を参照によって引き渡す場合、引き数が存在しなければ、引き数リスト内のアドレスはゼロです。

オプションの引き数を値によって引き渡す場合、引き数が存在しなければ値はゼロです。コンパイラーは追加のレジスター引き数を使用して、その値を通常のゼロ値と区別します。レジスターが値 1 を持っている場合は、オプションの引き数が存在します。値ゼロを持っている場合は、オプションの引き数は存在しません。

関連情報:
引き数リスト内の引き数の順序を参照してください。

INTENT 属性を持つ引き数

現在では、INTENT 属性を持つ引き数を宣言しても、プロシージャーに対するリンケージ規約は変更されません。しかし、この規則は将来変更される可能性があるので、Fortran 以外のプロシージャーから INTENT(IN) 引き数を持つ Fortran プロシージャーへの呼び出しはお勧めできません。

タイプのエンコードと検査

実行時エラーは見つけにくく、多くの場合、プロシージャー・インターフェースの不一致またはデータ定義の矛盾が原因です。 そのため、これらの問題のできるだけ多くをコンパイル時またはリンク時に見つけることが得策です。 オブジェクト・ファイルにタイプ情報を保管して、リンカーが不一致を検出できるようにするには、-qextchk コンパイラー・オプションを使用してください。


[ ページのトップ | 前ページ | 次ページ | 目次 | 索引 ]