お問い合わせ

ホーム > COBOLのはなし > COBOL利用技術のご紹介 -第3回- COBOLと他言語との連携 (その1−C言語)

COBOL利用技術のご紹介
-第3回- COBOLと他言語との連携 (その1−C言語)

COBOLコンソーシアム利用技術分科会
高木 渉 (日立製作所 ソフトウェア事業部)

PDF[約25キロバイト]

1.COBOLと他言語の連携の意味

 COBOLでいろいろなアプリケーションを記述することができる一方、他の言語で書かれたプログラムとの連携が必要になることがあります。たとえば、C言語で書かれたミドルウェアをCOBOLアプリケーションから呼び出して利用したり、COBOLアプリケーションを他の言語で書かれたアプリケーションが呼び出したりする場面があります。これらを実現するのが、他言語との連携機能です。

 COBOLと連携する他言語は複数ありますが、まずは基本となる連携として、C言語との連携を取り上げます。その他の言語との連携については別の機会に紹介します。

2.COBOLとC言語の連携

 C言語との連携は、COBOLの他言語連携の中でも中心的な役割を担います。

 C言語インターフェースは、各種のUNIX系やWindowsオペレーティングシステムで基本となる呼出しインターフェースで、C言語の関数呼出しでの制御の移し方、引数の渡し方、戻り値の戻し方などの振る舞いが、マシン命令に近いレベルで決まっています。多くのCOBOL実装は、CALL文の振る舞いをこのC言語インターフェースに合わせてあり、COBOLからC言語を呼び出すことも、またその逆のこともできるようになっています。

2.1 COBOLからCを呼ぶ場合

 COBOLからC言語の関数を呼び出す場合には、次の3点を注意します。

  1. 名前の対応(呼び出す先の関数名)
  2. 引数の渡し方の対応(COBOLのCALL文のUSING指定での、BY REFERENCE等の指定とC言語の引数)
  3. 型の対応(引数の型、および、構造を持つデータのメモリレイアウト)

 以下、これらについて説明します。

2.1.1 名前の対応

 C言語とCOBOLでは、プログラムに記述する名前(変数名、関数名など)に許される文字の構成が異なります。

 COBOLからC言語の関数を呼び出すには、CALL文を使い、C言語の関数名を定数または一意名の値として指定して呼び出すことになります。ただし、名前を一致させるには次のような問題があり、多くの場合COBOL処理系がなんらかの解決方法を用意しています。使用するCOBOL処理系とC言語処理系のマニュアルを参照してください。

  1. 名前に指定できる文字の種類が異なります。例えば、COBOLではハイフンが使えますが、C言語では使えません。
  2. 名前の長さの最大が異なります。COBOLでは30文字までですが、C言語では全体文字数の制限は無く、区別するべき先頭文字数が決められています。
  3. COBOLでは大文字と小文字は等価ですが、C言語では区別します。

2.1.2 引数の渡し方の対応

 まずは、他の言語との連携ではなく、COBOLからCOBOLを呼び出す際の引数の渡し方について説明します。COBOLのCALL文の引数には、BY REFERENCEまたはBY CONTENTを指定して渡し方を変えることができます。

 BY REFERENCEを指定した引数の場合、呼ばれるプログラムに渡すのは、値の格納された場所への参照であり「参照渡し」になります。この渡し方の特徴は、呼ぶ側と呼ばれる側で同じ格納場所を参照することです。変更すると呼ぶ側でもその変更が有効になります。

     01  BY-REF  PIC S9(9) BINARY.
     CALL  "kansuuA"  USING  BY REFERENCE  BY-REF.

 一方、BY CONTENTを指定した引数は、「内容渡し」になります。呼ばれる側で値を変更しても、その変更は呼ぶ側では有効になりません。内容を渡す方法としては、引数として指定されたデータ項目の値を別の場所に複製して、その場所への「参照」を、呼ばれるプログラムに渡します。こうして、呼ばれるプログラムで、BY REFERENCEとBY CONTENTを区別しなくても、共通に引数を受け取れます。受け取り方は共通ですが、BY CONTENTで渡された引数の値をいくら変更しても、呼び出し元には影響しません。

     01  BY-CONT  PIC S9(9) BINARY.
     CALL  "kansuuB"  USING  BY CONTENT  BY-CONT.

 では、COBOLの外との連携として、COBOLからCを呼ぶ場合を考えます。CALL文の引数がBY REFERENCEでもBY CONTENTでも、結局、渡されるのは参照ですので、C言語では、ポインタで受け取ります。このとき引数の名前は一致させる必要はありません。ポインタの先の値が本当に渡したい実体です。以下のコーディング例では、上の二つの例で制御を渡されるC言語の関数です。どちらも同じ構文になります。(型の対応については次節を参照。ここでは、COBOLのUSAGE BINARYとを対応させていますが、処理系に依存します。)

●BY REFERENCEで引数を渡されるC関数の例
●BY CONTENTで引数を渡されるC関数の例
void kansuuA(int *ByRef)
{
     /* 関数の処理 */
}

void kansuuB(int *ByCONT)
{
     /* 関数の処理 */
}

 現行規格の仕様としてはここまでですが、BY VALUE指定についても説明します。BY VALUE指定は、次期COBOL規格で導入されます。COBOL処理系によってはすでに拡張仕様になっています。この指定の場合、引数の渡し方は「値渡し」となり、上の二つの例のように参照が渡るのではなく、値が渡ります。実際には、スタック領域などに指定された引数の値を積み、呼ばれる側ではそのままその値を受け取ります。C言語との連携では、ポインタでなく、そのまま受け取ります。

     01  BY-VAL  PIC S9(9) BINARY.
     CALL  "kansuuC"  USING  BY VALUE  BY-VAL.


●BY VALUEで引数を渡されるC関数の例
     void kansuuC(int byVal)
     {
          /* 関数の処理 */
     }

 引数の戻し方に関連して、戻り値についても、ここで説明します。

 現在の規格COBOL(1985年規格)の範囲で、COBOLで呼出し元に値を返すには、BY REFERENCEを指定した引数を渡し、呼ばれる側でその内容を変更することで実現します。

 次期規格COBOLでは、CALL文に明示的にRETURNING指定を書くことで、戻り値用のデータ項目を指定できます。RETURNING指定もCOBOL処理系によってはすでに拡張仕様になっています。

     01  RETURN-VAL  PIC S9(9) BINARY.
     CALL  "kansuuD"  RETURNING  RETURN-VAL.
●戻り値を返すC関数の例
     int kansuuD()
     {
          int ret;
          /* 関数の処理 */
          return ret;
     }

 さらに、COBOLでの戻り値の受け取り方として、RETURN-CODE特殊レジスタという宣言無しに使用できる特別な変数を用意しているCOBOL処理系もあります。このレジスタは、たとえば、C言語では、4バイトの整数型に対応します。詳しくは、使用する処理系のマニュアルを参照してください。

2.1.3 型の対応

 すでに上の説明で暗黙のうちに使っていますが、値を正しく引き渡すために、引数の型の対応は重要です。たとえば、

     01 A PIC 9(9) USAGE BINARY.
と定義されていれば、ある実装ではC言語の4 byteの符号なし整数と対応します。(この対応は処理系に依存します。POSIXで定義された型である、USAGE COMPUTATIONAL-5を対応させる実装もあります。)

 また、COBOL集団項目中の基本データ項目の並べ方(レイアウト)は、C言語の構造体メンバの並べ方と同じとは限りません。隙間バイトの位置や個数が異なります。使用するCOBOLとCのそれぞれのマニュアルを見て、慎重に両者を合わせる必要があります。

 個々の型の対応とレイアウトは、処理系によって異なるため、ご使用になるCOBOL処理系のマニュアルとC言語のマニュアルを参照してください。

2.2 CからCOBOLを呼ぶ場合

 CからCOBOLを呼ぶ場合も、COBOLからCを呼ぶ場合と同じように、次の3点を注意する必要があります。

  1. 名前の対応(呼び出す先の関数名)
  2. 引数の渡し方の対応(COBOLの手続き部見出しのUSING指定での、BY REFERENCE等の指定とC言語の引数)
  3. 型の対応(引数の型、および、構造を持つデータのメモリレイアウト)

 これらのうち、(1)名前の対応 と (3) 型の対応については繰り返しになりますので割愛し、(2)の引数の渡し方の対応 について説明します。

2.2.1 引数の渡し方の対応

 今度は、COBOLで引数を受け取る場合の話から始めます。COBOLプログラムの手続き部見出し (PROCEDURE DIVISION header) にBY REFERENCEが指定された引数は、文字通り参照渡しで渡されることを期待しています。たとえば、

     IDENTIFICATION DIVISION.
     PROGRAM-ID.  BYREFPROG.
          :
     LINKAGE SECTION.
     01  BY-REF  PIC S9(9) USAGE BINARY.
     PROCEDURE DIVISION  USING  BY REFERENCE  BY-REF.
          :
となっているとき、呼ぶプログラムの側では、渡したい値の格納されている場所(アドレス)を指す「参照」を渡す必要があります。

 CからCOBOLを呼ぶときは、これに合わせて、次のように変数の参照を取得してから呼び出します。

     int ByRef;
     BYREFPROG(&ByRef);  /* 関数呼出し */

 また、次のようにCOBOLプログラム側がBY VALUE指定(値渡し)で引数を待っているときは、

     IDENTIFICATION DIVISION.
     PROGRAM-ID.  BYVALPROG.
          :
     LINKAGE SECTION.
     01  BY-VAL  PIC S9(9) USAGE BINARY.
     PROCEDURE DIVISION  USING  BY VALUE  BY-VAL.
          :

 C関数から呼ぶには、値そのものを渡す必要があります。C言語では次のようにそのまま引数を指定すれば対応が取れます。

     int ByVal;
     BYREFPROG(ByVal);  /* 関数呼出し */

 戻り値についても、COBOLからCを呼び出す場合と同様です。なお、先に2.1.2で述べたように戻り値の指定は拡張仕様ですので、詳細は処理系によります。

 CからCOBOLを呼ぶとき、COBOL側の手続き部見出しにRETURNING指定があれば、C側では、戻り値が帰ってくるものとしてプログラミングできます。COBOL側でRETURN-CODE特殊レジスタに値を設定すると、Cに制御が戻ったときに、その値がたとえば、整数型の関数値として利用できます。

3.まとめ

 以上のように、言語仕様の差にさえ気をつければ、COBOLとC言語との相互連携は、特別な仕組みやプログラミング無しにできます。

− 第3回 終 −