19.1.3 COBOLプログラムからCプログラムを呼び出す方法

COBOLプログラムからCプログラムを呼ぶときの規則を示します。

<この項の構成>
(1) COBOLからCを呼ぶときの規則
(2) Cプログラムの型とCOBOLでの宣言
(3) 引数の受け渡し
(4) 戻り値の受け渡し

(1) COBOLからCを呼ぶときの規則

(2) Cプログラムの型とCOBOLでの宣言

Cプログラムのデータ型と,対応するCOBOLのデータ項目の型を,次に示します。

Cプログラムのデータ型対応するCOBOLのデータ項目の型
unsigned char-Bin1Byte指定あり符号なし2進項目(1~2けた)

9(1) COMP ~ 9(2) COMP

-Bin1Byte指定なし

9(1) COMP-X ~ 9(2) COMP-X

英数字項目(1けた)

X(1)

char-Bin1Byte指定あり符号付き2進項目(1~2けた)

S9(1) COMP ~ S9(2) COMP※5

英数字項目(1けた)

X(1)

unsigned short符号なし2進項目(3~4けた)

9(3) COMP ~ 9(4) COMP
9(3) COMP-X ~ 9(4) COMP-X

short符号付き2進項目(3~4けた)

S9(3) COMP ~ S9(4) COMP

unsigned int符号なし2進項目(5~9けた)

9(5) COMP ~ 9(9) COMP
9(5) COMP-X ~ 9(9) COMP-X

int符号付き2進項目(5~9けた)

S9(5) COMP ~ S9(9) COMP

unsigned long符号なし2進項目(5~9けた)※1

9(5) COMP ~ 9(9) COMP
9(5) COMP-X ~ 9(9) COMP-X

符号なし2進項目(10~18けた)※2

9(10) COMP ~ 9(18) COMP
9(10) COMP-X ~ 9(18) COMP-X

long符号付き2進項目(5~9けた)※1

S9(5) COMP ~ S9(9) COMP

符号付き2進項目(10~18けた)※2

S9(10) COMP ~ S9(18) COMP

unsigned long long※4符号なし2進項目(10~18けた)

9(10) COMP ~ 9(18) COMP
9(10) COMP-X ~ 9(18) COMP-X

long long※4符号付き2進項目(10~18けた)

S9(10) COMP ~ S9(18) COMP

float単精度内部浮動小数点数字項目

COMP-1

double倍精度内部浮動小数点数字項目

COMP-2

ポインタ型アドレス名,アドレスデータ項目

ADDRESS

配列型アドレスデータ項目

ADDRESS

構造体※3集団項目
(凡例)
-:該当しない
注※1 UNIX32の場合です。
注※2 UNIX64の場合です。
注※3
COBOLの集団項目を受け渡しする場合,Cプログラムでの境界調整を考慮して引数のデータ項目を定義する必要があります。
COBOLの集団項目は,標準では各基本項目がすき間なく配置されるのに対し,Cプログラムでは計算機固有の境界に従って配置されます。このため,あらかじめ境界調整される分の未使用領域を定義しておくなど,計算機固有の境界調整を意識したデータを定義しておくことを推奨します。
なお,COBOLでは,SYNCHRONIZED句を指定することで計算機固有の境界調整に従って各基本項目を配置できます。
HP-UX(IPF),HP-UX(IPF64),およびLinux(IPF64)では,プラットフォームの規約とCOBOL言語仕様の差異によって,C言語モジュールとの間で次の構造体を値渡しの引数,または返却値として受け渡しした場合の動作は保証しません。
・float型のメンバだけで構成された構造体
・double型のメンバだけで構成された構造体
Linux(x64)では,プラットフォームの規約とCOBOL言語仕様の差異によって,従属項目として内部浮動小数点項目をもつ16バイト以下の集団項目を値渡し(BY VALUE)の引数および返却項目に指定した場合,C言語プログラムとの間での引数および返却項目の受け渡しは保証しません。
このような場合,次に示すどれかの方法でプログラムを修正する必要があります。
・集団項目ではなく同じサイズの文字列項目として値の受け渡しをする。
・値渡しではなく参照渡し(BY REFERENCE)または内容渡し(BY CONTENT)に変更する。
・集団項目のサイズが16バイトを超えるようにする。
なお,-Lx64ConventionCheckオプションを指定すると,次の条件を満たす場合に警告レベルのエラーメッセージが出力されます。
1. サイズが16バイト以下の集団項目を値渡しの引数および返却項目に指定している。
2. 1.の集団項目の従属項目に内部浮動小数点項目がある。
Linux(x86)では,プラットフォームの規約とCOBOL言語仕様の差異によって,サイズが1バイトのCOBOL集団項目とサイズが1バイトのC言語構造体との間で返却項目の受け渡しはできません。
HP-UX(IPF),HP-UX(IPF64),AIX(32),AIX(64),およびSolaris(SPARC)では,プラットフォームの規約とCOBOL言語仕様の差異によって,サイズが1バイトのCOBOL集団項目とサイズが1バイトのC言語構造体との間で値渡し(BY VALUE)の引数および返却項目の受け渡しはできません。
注※4 Solaris(SPARC)の場合,値渡し(BY VALUE)引数および返却項目のとき,C言語のlong long型またはunsigned long long型の変数と値の受け渡しはできません。
注※5 符号修飾子を省略したとき,unsigned charと解釈するCコンパイラを使用する場合,明示的にsigned charと書くか,または適切なCコンパイラのオプションを指定してsigned charと解釈されるようにする必要がある。

(3) 引数の受け渡し

COBOLプログラムからCプログラムへ引数を渡す方法を,次に示します。

(a) 引数をポインタ型で引き渡す
COBOLプログラム

          :
      WORKING-STORAGE SECTION.
      01 CNT PIC S9(9) USAGE COMP.
      01 STR.
        02 STRCHAR PIC X(79).
        02 FILLER  PIC X VALUE LOW-VALUE.
          :
      PROCEDURE DIVISION.
          :
        CALL 'sample2' USING BY REFERENCE CNT STR.
          :

Cプログラム

int  sample2(int *cnt, char *str)
{
   :
 return(0);
}

(b) 引数を値渡しで引き渡す
COBOLプログラム

          :
      WORKING-STORAGE SECTION.
      01 CNT PIC S9(9) USAGE COMP.
      01 STR PIC X(1).
          :
      PROCEDURE DIVISION.
          :
        CALL 'sample2' USING BY VALUE CNT STR.
          :

Cプログラム

int  sample2(int cnt, char str)
{
   :
 return(0);
}

(c) CALL文の引数にADDRESS OF 一意名,LENGTH OF 一意名を指定した例
COBOL主プログラム

      IDENTIFICATION DIVISION.
      PROGRAM-ID. SAMPLE1.
      DATA DIVISION.
      WORKING-STORAGE SECTION.
      01 WK-1.
        02 W01    PIC X(30)
           VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234'.
        02 FILLER PIC X VALUE LOW-VALUE. …5.
      PROCEDURE  DIVISION.
          CALL 'SAMPLE2'
               USING BY REFERENCE WK-1. …1.
          CALL 'SAMPLE3'
               USING BY REFERENCE ADDRESS OF WK-1. …2.
          CALL 'SAMPLE4'
               USING BY CONTENT LENGTH  OF WK-1. …3.
          CALL 'SAMPLE5'
               USING BY VALUE LENGTH  OF WK-1. …4.
          STOP RUN.
      END PROGRAM SAMPLE1.

C副プログラム

#include <stdio.h>
int SAMPLE2(char *p_ptr_r)
{
  printf("first char(r) =(%s)¥n",p_ptr_r);   … 1.
   :
}
int SAMPLE3(char **p_ptr_ra)
{
  printf("first char(ra)=(%s)¥n",*p_ptr_ra);   … 2.
   :
}
int SAMPLE4(
    int *p_ptr_cl  /* この引数の型はUNIX32の場合  */
                   /* UNIX64の場合は long long *  */
    )
{
  printf("length(p)     =(%d)¥n",*p_ptr_cl);   … 3.
   :
}
int SAMPLE5(
    int p_ptr_vl  /* この引数の型はUNIX32の場合  */
                  /* UNIX64の場合は long long    */
    )
{
  printf("length(p)     =(%d)¥n",p_ptr_vl);   … 4.
   :
}

  1. BY REFERENCE指定のCALL文で渡される値は,指定された一意名のアドレスです。
  2. ADDRESS OFで修飾した場合に渡される値は,一意名のアドレスではなく,一意名のアドレスが入っている領域のアドレスとなります。
  3. LENGTH OFで修飾したCONTENT指定では,一意名の長さが入っている領域のアドレスが渡されます。
  4. LENGTH OFで修飾したVALUE指定では,一意名の長さが値として渡されます。
  5. Cプログラム中で文字列として参照するため,COBOLプログラム中で英数字項目の終端にNULL文字(X'00')を設定しています。
BY REFERENCE指定で渡される引数の値
[図データ]
実行結果

first char(r) =(ABCDEFGHIJKLMNOPQRSTUVWXYZ1234)
   :
first char(ra)=(ABCDEFGHIJKLMNOPQRSTUVWXYZ1234)
   :
length(p)     =(31)
   :
length(p)     =(31)
   :

(4) 戻り値の受け渡し

CプログラムからCOBOLプログラムへ戻り値を返す方法を,次に示します。

(a) 整数型のデータ項目をリターンする例
COBOLプログラム

      WORKING-STORAGE SECTION.
      01 RTC PIC S9(9) USAGE COMP.
          :
      PROCEDURE DIVISION.
          :
          CALL 'sample2' RETURNING RTC.

Cプログラム

int sample2()
 {
 int rtc;
   :
 return (rtc);
 }

(b) 構造体型のデータ項目をリターンする例

構造体型のデータ項目をリターンする場合,COBOLプログラムとCプログラムでは境界調整によってデータのマッピング方法が異なることがあるので注意が必要です。

COBOLプログラム

      WORKING-STORAGE SECTION.
      01 TBL.
        02 A PIC S9(9) USAGE COMP.
        02 B PIC X(10).
          :
      PROCEDURE DIVISION.
          :
          CALL 'sample2' RETURNING TBL.

Cプログラム

struct tbl {int a; char b[10];};
struct tbl sample2()
{
   struct tbl rtn;
   :
   return (rtn);
}

注意事項
C言語の構造体の場合,要素の境界調整でパディング(領域間のギャップを埋めるために挿入される暗黙のFILLER項目)が挿入されます。そのほかに,構造体のサイズを最大の基本要素サイズの倍数に切り上げるため,パディングが挿入されることがあります。この場合,パディングは構造体の末尾に挿入されます。例えば上記の例の構造体tblの場合,要素の合計のサイズはCOBOLの集団項目TBLと同じ14バイトですが,構造体のサイズを4バイト(最大の基本要素のサイズ)の倍数の16バイトにするために,2バイトのパディングが構造体の末尾に挿入されます。このため,COBOLの集団項目TBLとはサイズが不一致になります。プラットフォームによっては,このサイズの不一致が原因で,引数や戻り値の受け渡しで異常終了や結果不正となることがあるため,次のどちらかの方法でC言語の構造体のサイズとCOBOLの集団項目のサイズを一致させる必要があります。
  • C言語の構造体のサイズをCOBOLの集団項目のサイズに合わせる方法
    構造体を詰めて配置するC言語の機能(C言語の言語仕様の#pragma packやC言語のコンパイラのコンパイラオプションで提供されている)を使って構造体tblのサイズを14バイトにします。構造体を詰めて配置するC言語の機能については,各システムのCコンパイラのリファレンスを参照してください。
  • COBOLの集団項目のサイズをC言語の構造体のサイズに合わせる方法
    COBOLの集団項目TBLのサイズを16バイトにするために,COBOLの集団項目TBLの末尾に次の2バイト分のFILLER項目を追加してください。

  02 FILLER PIC X(2).