ILEでのプログラム作成
ILE(統合言語環境)で構築したシステムは、ダイナミックリンクのオーバーヘッドがなくなり、
高い処理効率が得られるようになります。特にチューンナップしていないプログラムとの比較では
ざっと100倍の効率アップが得られるようです。
ILEでシステム構築をする場合、同一言語でのバインドだけでなく、RPGとCOBOLや
COBOLとC言語など異なる言語をバインドしてのプログラム組み立てとなることもあります。
ここでは、実際に異なる言語のモジュールを組み合わせてプログラム構築を試してみました。
別々のコンパイルタイミングでのモジュールの作成
チーム・プレーでプログラム開発を行う場合、プログラムを適当に分割して、別々のタイミングで開発し、
ソース → モジュール → プログラム
の手順の分割建造法をとることになります。
その場合の手順、注意点について紹介します。
分割建造法の手順
手順はモジュールとよばれる中間製品を作成し、これをバインドして一つの実行可能プログラムにします。
その手順は次のとおりです。
手順1.モジュールの作成
言語の種類を問わず、コーディングをおえたなら、モジュール(*MODULE)を作成します。
モジュールの作成は独立して(それぞれ別々のタイミングで)行われます。
モジュール作成のCLは次のとおりです。例はILE−RPGです。
CRTRPGMOD MODULE(WRKLIB/TEST4R) SRCFILE(*LIBL/QRPGLESRC)
CRTRPGMOD MODULE(WRKLIB/TEST4R1) SRCFILE(*LIBL/QRPGLESRC)
手順2.実行プログラムの作成
それぞれのモジュールが完成したなら、それらをバインド(汎用機のリンクエディット)して
ひとつのプログラムをくみ上げます。以下はその例です。これは言語の種類によりません。
CRTPGM PGM(WRKLIB/TEST4R) MODULE(*LIBL/TEST4R *LIBL/TEST4R1) +
DETAIL(*BASIC)
DETAILパラメータはバインドの結果のレポートの詳しさです。
ここでは*BASICを指定しています。
手順3.実行
通常のプログラムと同様に直接CALLあるいは,サブミット、あるいはメニューから呼び出しで
実行します。
CALL PGM(WRKLIB/TEST4R)
ILE−RPGのページでもふれましたが、RPGの場合呼び出し側にプロトタイプの定義が必要です。
以下にサンプルを示します。
メイン・プロシージャー(TEST4R)
H DATEDIT(*YMD-) D*------------------------------------ D* プロトタイプの指定 D TEST4R1 PR D 4A D 9B 0 D 9P 0 D*------------------------------------ D AA S 4A D BB S 9B 0 D CC S 9P 0 C*------------------------------------ C MOVEL '1234' AA C Z-ADD 9876 BB C Z-ADD 000 CC C* C CALLP TEST4R1 (AA: BB: CC) C AA DSPLY C BB DSPLY C CC DSPLY C SETON C RETURN
注意点:バインド予定のプロシージャーの呼び出しは、CALLP命令を使用します。
サブ・プロシージャー(TEST4R1)
H NOMAIN DTEST4R1 PR D AA 4A D BB 10I 0 D CC 9P 0 PTEST4R1 B EXPORT D*------------------------------------ DTEST4R1 PI D AA 4A D BB 10I 0 D CC 9P 0 C*------------------------------------ C* C MOVEL 'ABCD' AA C BB DIV 2 BB C BB MULT 3 CC C* C RETURN C SETON LR P E
サブ・プロシージャーではEXPORTパラメータで「外部」、「入り口」の属性を与えます。(下線部)
EXPORTされていないと、外部からTEST4R1の入口点が見えません。
CRTPGMでは一見正常にバインドが完了しますが、実行するとCALLがかかったとき、
エラーになってしまいます。(本来ならCRTPGMでエラーにすべきと思うのですが)
また、モジュール名と入口名が別のとき、たとえばメインがSUB1をCALLPしていて、
サブのモジュール名がSUB1,入口名がSUB1Aのときは、CRTPGMは正常に完了するが、
できあがったプログラムは実行しても正常にRUNしません。
異なった言語からのモジュールのバインド
RPG,COBOL,CL,Cなど異なった言語でできたモジュールの組合せを試してみました。
ここではプロシージャー名は次のように命名しています。
メイン サブ RPG−IV TEST4R TEST4R1 COBOL TESTCB TESTCB1 CL ( TESTCL) TESTCL1 C TESTC TESTC1
1. RPGメインからRPG,COB,CL,Cの呼出し
RPGをメインとして各種の言語のプロシージャーを呼び出しを行っています。
RPGメイン(TEST4R)のソース
H DATEDIT(*YMD-) D*---------------------------------------------------- D* プロトタイプの指定 D TEST4R1 PR D 10A D 9B 0 D 9P 0 D 8F D TESTCB1 PR D 10A D 9B 0 D 9P 0 D 8F D TESTCL1 PR D 10A D 9B 0 D 9P 0 D 8F D TESTC1 PR D 10A D 9B 0 D 9P 0 D 8F D*---------------------------------------------------- C MOVEL *BLANK AA C Z-ADD 12345 BB C Z-ADD 000 CC C Z-ADD 000 DD C* --> RPG C CALLP TEST4R1 (AA: BB: CC: DD) C EXSR SBDSP C* --> COB C CALLP TESTCB1 (AA: BB: CC: DD) C EXSR SBDSP C* --> CL1 C CALLP TESTCB1 (AA: BB: CC: DD) C EXSR SBDSP C* --> C1 C CALLP TESTC1 (AA: BB: CC: DD) C EXSR SBDSP C* C SETON LR C RETURN C*---------------------------------------------- C* SBDSP DSPLAY C*---------------------------------------------- C SBDSP BEGSR C* C AA DSPLY C BB DSPLY C CC DSPLY C DD DSPLY C* C ENDSR
注意:呼び出しするプロシージャーのプロトタイプをすべて宣言しています。
呼び出しはCALLPです。
受け渡しするパラメータは10バイトの文字列、4バイトのバイナリー、9桁の
パック10進数、倍精度の浮動小数点数です。
RPGサブのソース
H NOMAIN DTEST4R1 PR D AA 10A D BB 10I 0 D CC 9P 0 D DD 8F PTEST4R1 B EXPORT D*------------------------------------ DTEST4R1 PI D AA 10A D BB 10I 0 D CC 9P 0 D DD 8F C*------------------------------------ C* C MOVEL 'TEST4R1...' AA C BB DIV 3 BB C BB MULT 4 CC C CC DIV 5 DD C* C RETURN C SETON LR P E
もらった数値データの1/3と4/3と4/15を計算して返しています。
COBOLサブ・プログラム・ソース
PROCESS APOST IDENTIFICATION DIVISION. PROGRAM-ID. TESTCB1. AUTHOR. KAJIROU. ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. HAL-5000. OBJECT-COMPUTER. HAL-5000. INPUT-OUTPUT SECTION. FILE-CONTROL. *---------------------------------------------------------- DATA DIVISION. WORKING-STORAGE SECTION. LINKAGE SECTION. 01 AAA PIC X(10). 01 BBB PIC S9(09) COMP-4. 01 CCC PIC S9(09) COMP-3. 01 DDD COMP-2. *--------------------------------------------------------------- PROCEDURE DIVISION USING AAA BBB CCC DDD. 01. MOVE 'TESTCB1...' TO AAA. COMPUTE BBB = BBB / 2. COMPUTE CCC = BBB * 3. COMPUTE DDD = CCC / 4. GOBACK.
もらった数値データの1/2と3/2と3/8を計算して返しています。
CLサブプログラム(TESTCL1)のソース
PGM PARM(&AA &BB &CC &DD) DCL &AA *CHAR 10 /* 文字列 */ DCL &BB *CHAR 4 /* 2進数用 */ DCL &CC *DEC 9 /* パック10進数 */ DCL &DD *CHAR 8 /* 浮動小数点用 */ DCL &WK *CHAR 2 /* 2進数用ワーク */ CHGVAR &AA VALUE('TESTCL1...') CHGVAR &WK VALUE(%SST(&BB 3 2)) CHGVAR &CC VALUE(%BIN(&BB) * 5)
CLプログラムではバイナリーはサポートしていません。そのため、このプログラムでは
&BBで取得した4バイトバイナリーの下2バイト分をバイナリーとして解釈して計算し、
2倍にして&CCで返しています。また、浮動小数点数もサポートしていないので、
同じバイト数のパラメータだけ用意するだけで、何もしていません。
呼出しプログラムは9桁のパック10進数で受け取ります。
Cプログラム(TESTC1)のソース
#include <unistd.h> #include <decimal.h> /* パック10進数を使うとき必要 */ void TESTC1(char *AA, int *BB, decimal(9,0) *CC, double *DD) { memcpy(AA, "TESTC1....", 10); *BB = *BB / 5 ; *CC = (decimal(9,0)) (*BB *6); *DD = (float) *CC / 7; return; }
このプログラムではもらった数値データの1/5と6/5と6/35を計算してかえしています。
プログラム作成手順は次のようになります。
手順.1モジュールの作成
CRTRPGMOD MODULE(WRKLIB/TEST4R) SRCFILE(*LIBL/QRPGLESRC)
CRTRPGMOD MODULE(WRKLIB/TESTC4R1) SRCFILE(*LIBL/QRPGLESRC)
CRTCBLMOD MODULE(WRKLIB/TESTCCB1) SRCFILE(*LIBL/QCBLLESRC)
CRTCBLMOD MODULE(WRKLIB/TESTCCL1) SRCFILE(*LIBL/QCLLESRC)
CRTCBLMOD MODULE(WRKLIB/TESTC1) SRCFILE(*LIBL/QCSRC)
手順.2バインド・プログラムの作成
CRTPGM PGM(WRKLIB/TEST4R) MODULE(TEST4R TEST4R1 TESTCB1 TESTCL1 TESTC1) -
DETAIL(*BASIC)
2.COBがメインの場合 COB,RPG,CL,C
COBOメイン・プログラム
PROCESS APOST IDENTIFICATION DIVISION. PROGRAM-ID. TESTCB. AUTHOR. KAJIROU. ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. HAL-5000. OBJECT-COMPUTER. HAL-5000. INPUT-OUTPUT SECTION. FILE-CONTROL. *---------------------------------------------------------- DATA DIVISION. *---------------------------------------------------------- WORKING-STORAGE SECTION. 01 AA PIC X(10). 01 BB PIC S9(09) COMP-4. 01 CC PIC S9(09) COMP-3. 01 DD COMP-2. *--------------------------------------------------------------- PROCEDURE DIVISION. 01. MOVE SPACE TO AA. MOVE 12345 TO BB. MOVE 0 TO CC. MOVE 0 TO DD. 02. CALL PROCEDURE 'TESTCB1' USING AA BB CC DD. DISPLAY 'AA=' AA ' BB=' BB ' CC=' CC ' DD=' DD. CALL PROCEDURE 'TEST4R1' USING AA BB CC DD. DISPLAY 'AA=' AA ' BB=' BB ' CC=' CC ' DD=' DD. CALL PROCEDURE 'TESTCL1' USING AA BB CC DD. DISPLAY 'AA=' AA ' BB=' BB ' CC=' CC ' DD=' DD. CALL PROCEDURE 'TESTC1' USING AA BB CC DD. DISPLAY 'AA=' AA ' BB=' BB ' CC=' CC ' DD=' DD. 03. STOP RUN.
注意:CALL命令はLINKAGE TYPE IS PROCEDUREです。
これをつけないと、一見バインドが正常に終わったように見えても実行時にエラーになります。
LINKAGE TYPE ISは省略可能なので略しています。
各サブ・プログラム
既出、省略します。
プログラム作成手順
手順1.モジュール作成
省略
手順2.プログラム作成
CRTPGM PGM(WRKLIB/TESTCB) MODULE(TESTCB TEST4R1 TESTCB1 TESTCL1 TESTC1) -
DETAIL(*BASIC)
3.C言語によるメイン・プログラム
#include <stdio.h> #include <stdlib.h> #include <unistd.h> /* for memcpy */ #include <decimal.h> /* パック10進数を使うとき必要 */ void TEST4R1(char *AA, int *BB, decimal(9,0) *CC, double *DD); void TESTCB1(char *AA, int *BB, decimal(9,0) *CC, double *DD); void TESTCL1(char *AA, int *BB, decimal(9,0) *CC, double *DD); void TESTC1(char *AA, int *BB, decimal(9,0) *CC, double *DD); void main(int argc, char *argv[]) { char AA[10]; /* 文字列 */ int BB ; /* INTEGER*4 */ decimal(9,0) CC ; /* パック10進数 */ double DD ; /* REAL*8 */ int WK ; /* INTEGER*4 WORK */ memcpy(AA, " ", 10); BB = 12345; CC = 0 ; DD = 0 ; TEST4R1(AA, &BB, &CC, &DD); /* CALL TEST4R1(AA,BB,CC,DD) */ WK = (int) CC; printf(" AA= %10s BB= %d CC=%d DD=%f ??/n", AA,BB,WK,DD); TESTCB1(AA, &BB, &CC, &DD); /* CALL TESTCB1(AA,BB,CC,DD) */ WK = (int) CC; printf(" AA= %s BB= %d CC=%d DD=%f ??/n", AA,BB,WK,DD); TESTCL1(AA, &BB, &CC, &DD); /* CALL TESTCL1(AA,BB,CC,DD) */ WK = (int) CC; printf(" AA= %s BB= %d CC=%d DD=%f ??/n", AA,BB,WK,DD); TESTC1(AA, &BB, &CC, &DD); /* CALL TESTC1(AA,BB,CC,DD) */ WK = (int) CC; printf(" AA= %s BB= %d CC=%d DD=%f ??/n", AA,BB,WK,DD); return; }
プログラム作成手順
手順1.モジュールの作成
省略
手順2.バインド・プログラムの作成
CRTPGM PGM(WRKLIB/TESTC) MODULE(TESTC TEST4R1 TESTCB1 TESTCL1 TESTC1) -
DETAIL(*BASIC)
スタティック・エクスターナルを使ったデータの受渡し
モジュール間のデータ受渡しの方法として、各モジュールが外部のメモリーエリアを共通にアクセスする
という方法があります。FORTRANなどではCOMMONエリアとして早くから利用されていた方法です。
ILEの体系ではその方法が可能になっています。
COBOL
WORKING−STORAGEでEXTERNALの構造を定義します。
01項目の名前が共通外部メモリーエリアの名前になります。
PROCESS APOST IDENTIFICATION DIVISION. PROGRAM-ID. TSTCB. AUTHOR. KAJIROU. ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. HAL-5000. OBJECT-COMPUTER. HAL-5000. INPUT-OUTPUT SECTION. FILE-CONTROL. *---------------------------------------------------------- DATA DIVISION. WORKING-STORAGE SECTION. 01 P EXTERNAL. 03 AA PIC X(10). 03 BB PIC S9(09) COMP-4. 03 CC PIC S9(09) COMP-3. 03 DD COMP-2. 03 EEE. 05 EE OCCURS 3 COMP-2. 03 FF PIC X(10). *---------------------------------------------------------- PROCEDURE DIVISION. 01. MOVE SPACE TO AA. MOVE 12345 TO BB. MOVE 0 TO CC. MOVE 0 TO DD. 02. CALL PROCEDURE 'TSTCB1'. DISPLAY 'AA=' AA ' BB=' BB ' CC=' CC ' DD=' DD ' EE1=' EE(1) ' EE2=' EE(2) ' EE3=' EE(3). DISPLAY 'FF=' FF. CALL PROCEDURE 'TST4R1'. DISPLAY 'AA=' AA ' BB=' BB ' CC=' CC ' DD=' DD ' EE1=' EE(1) ' EE2=' EE(2) ' EE3=' EE(3). CALL PROCEDURE 'TSTC1'. DISPLAY 'AA=' AA ' BB=' BB ' CC=' CC ' DD=' DD ' EE1=' EE(1) ' EE2=' EE(2) ' EE3=' EE(3). DISPLAY 'FF=' FF. 03. STOP RUN.
サブプロシージャーでも同様にEXTERNALの構造を定義します。
DATA DIVISION. WORKING-STORAGE SECTION. 01 P EXTERNAL. 03 AAA PIC X(10). 03 BBB PIC S9(09) COMP-4. 03 CCC PIC S9(09) COMP-3. 03 DDD COMP-2. 03 EE. 05 EEE OCCURS 3 COMP-2. 03 FFF PIC X(10).
RPG
ILE−RPGの場合はDS(データ構造)を定義して、EXPORTの属性をつけます。
EXPORTパラメータで名前をつければ、そちらの名前がDSの名前にに優先されます。
H NOMAIN D P DS EXPORT('P') D AA 10A D BB 10I 0 D CC 9P 0 D DD 8F D EE 8F DIM(3) D FF 10A DTST4R1 PR PTST4R1 B EXPORT C*------------------------------------ C* C MOVEL 'TST4R1....' AA C BB DIV 3 BB C BB MULT 4 CC C CC DIV 5 DD C BB MULT 10 EE(1) C BB MULT 100 EE(2) C BB MULT 1000 EE(3) C MOVE 'PQRSTUVWXY' FF C* C RETURN C SETON LR PTST4R1 E
C
extern参照の属性をもった構造(struct)を定義します。境界合わせに注意して下さい。
structのタグが外部メモリーエリアの名前になります。
#include <unistd.h> #include <decimal.h> /* パック10進数を使うとき必要 */ void TSTC1() { extern _Packed struct PARM1 { char AA[10]; int BB ; decimal(9,0) CC ; double DD ; double EE[3] ; char FF[10]; } P ; /* 外部メモリーエリア名 */ memcpy(P.AA, "TSTC1-ABCD", 10); memcpy(P.FF, "IJKLMNOPQR", 10); P.BB = P.BB / 5 ; P.CC = (decimal(9,0)) (P.BB *6); P.DD = (float) (P.CC / 7); P.EE[2] = 0 ; P.EE[0] = (float) P.BB * 10; P.EE[1] = (float) P.BB * 100; P.EE[2] = (float) P.BB * 1000; return; }
バインド
以上のモジュールをCRTPGMコマンドでバインドすると、プログラムができあがります。
CRTPGM PGM(WRKLIB/TSTCB) MODULE(TSTCB TSTCB1 TST4R1 TSTC1)
目 次 へ
(C)COPYRIGHT ISHIOKA KATSUHIDE 2000