ILE RPG サブプロシージャの使い方 (7) - サービス・プログラムの世代管理 -

ILE RPG サブプロシージャの使い方 (2) - サブプロシージャからサブプロシージャを呼び出す -」でサンプルとして参照させていただいた「C による統計データ解析入門」の中に、さらに↓のような例題が続きとして載っています。

関数を使う関数をさらに使う関数を定義することができる、ということの例になっていますね。

/* Program 2-5(組み合せ数計算のプログラム) */

#include <stdio.h>
double factorial(int n);
double perm(int m, int n);
double comb(int n, int r);

void main()
{
  double k;
  int n, r;
    n=5;
    r=2;
    k=comb(n,r);
    printf("C(%d",n);
    printf(",%d",r);
    printf(")=%f\n",k);
}

double factorial(int n)
{
   int i, m;
   double k;
   k=1;
     if(n == 0) 
     m=1;
     else 
     m=n;
   for(i=1; i<=m; i++) 
   k=k*i;
     return k;
}

double perm(int n, int r)
{
  int nr; 
  double n1, nr1, p; 
    nr = n - r;
    n1 = factorial(n);
    nr1 = factorial(nr);
    p = n1 / nr1;
return p;
}

double comb(int n, int r)
{
   double c, p, r1; 
   p = perm(n, r);
   r1 = factorial(r);
   c = p / r1;
   return c;
}

こうなるともう、サービス・プログラムを利用するのが妥当な選択肢になりますね。

サービス・プログラムを利用するという前提で考えれば、メイン・プログラムにサブプロシージャの処理を記述する必要はありません。
使用するサブプロシージャ(関数)のプロトタイプ定義を記述するだけになります。

ILE RPG で書き直したメインの処理

まず、メインの処理を作成してみましょう。
関数を切り離したメインの部分をかなり忠実に ILE RPG に移してみたものが↓になります。

TESTFPC

      *                                                                                             
      * CRTRPGMOD MODULE(TESTFPC) SRCFILE(QRPGLESRC) DBGVIEW(*SOURCE)                               
      * CRTSRVPGM SRVPGM(MATH) MODULE(FACTORIAL PERM COMB) SRCFILE(QSRVSRC)                         
      *                                                                                             
      * CRTPGM PGM(TESTFPC) MODULE(TESTFPC) BNDSRVPGM(MATH)                                         
      *                                                                                             
     D k               S             10i 0                                                          
     D r               S             10i 0                                                          
     D n               S             10i 0                                                          
      *                                                                                             
     DComb             PR             8f                                                            
     D p1                            10i 0                                                          
     D p2                            10i 0                                                          
      *                                                                                             
      /free                                                                                         
                                                                                                    
          n = 5 ;                                                                                   
          r = 2 ;                                                                                   
          k = comb(n : r) ;                                                                         
          dsply  %char(k) ;                                                                         
          return ;                                                                                  
                                                                                                    
      /end-free                                                                                     
      *                                                                                             

CRTRPGMOD コマンドでモジュールを作成します。

サブプロシージャの作成

サブプロシージャの方のソースです。

今までに作成した Factorial サブプロシージャ、Perm サブプロシージャをサブプロシージャの中から両方とも使います。
それぞれのプロトタイプ宣言が定義されているのがわかりますね。

      *                                                                                             
      * CRTRPGMOD MODULE(COMB) SRCFILE(QRPGLESRC) DBGVIEW(*SOURCE)                                  
      *                                                                                             
     H NOMAIN                                                                                       
      *                                                                                             
     Dcomb             PR             8f                                                            
     D p1                            10i 0                                                          
     D p2                            10i 0                                                          
      *                                                                                             
     Pcomb             B                   EXPORT                                                   
     Dcomb             PI             8f                                                            
     D n                             10i 0                                                          
     D r                             10i 0                                                          
      *                                                                                             
     D nr              S             10i 0                                                          
     D c               S              8f                                                            
     D p               S              8f                                                            
     D r1              S              8f                                                            
      *                                                                                             
     Dperm             PR             8f                                                            
     D p1                            10i 0                                                          
     D p2                            10i 0                                                          
      *                                                                                             
     Dfactorial        PR             8f                                                            
     D p1                            10i 0                                                          
      *                                                                                             
      /free                                                                                         
                                                                                                    
          nr = n - r ;                                                                              
                                                                                                    
          p = perm(n : r) ;                                                                         
          r1 = factorial(r) ;                                                                       
          c = p / r1 ;                                                                              
                                                                                                    
          return c ;                                                                                
                                                                                                    
      /end-free                                                                                     
     Pcomb             E                                                                            
      *                                                                                             

CRTRPGMOD コマンドでモジュールを作成します。

新しいサブプロシージャのサービス・プログラムへの追加

このサブプロシージャもサービス・プログラムに追加して共有することにしましょう。

サービス・プログラムを作成するときに記述した BND ソースに新しいサブプロシージャの定義を追加します。

↑のソースを元に、新しいサブプロシージャをモジュールに追加してサービス・プログラムを作成し直します。
新しいサブプロシージャの追加なので、UPDSRVPGM コマンドなどは使えないので、CRTSRVPGM コマンドでの作り直しということになります。

新しいサービス・プログラムを使用する、新しいプログラムを作成します。
CRTPGM コマンドで実行可能プログラムを作成するわけです。

これで今回のプログラムは動くようになりました。

新規サブプロシージャを追加する前のサービス・プログラムを使用していたプログラムは?

今回新しくサブプロシージャを追加しただけなので、同じサービス・プログラムを使用している前回のプログラムは動くはずですね。

そこで動かしてみると、、

エラーになってしまうようになってしまいました。。

エラー・メッセージをよく見てみましょう。
「サービス・プログラム・インターフェースが変更されました」とのことです。
確かにサービス・プログラムは、新しいモジュールを追加して作り直していますね。。

しかし「記号」とは何のことでしょうか??

文面を見る限り、プログラムにその情報がありそうです。

サービス・プログラムの"シグネチャ"とは

実は DSPPGM PGM(PROCTEST/TESTFP_SP) コマンドでプログラムの属性を見てみると、その中に↓のような情報があるのを見つけられます。

MATH というサービス・プログラムにのメッセージに表示されているのと同じ"記号"が割り当てられているのがわかりますね。

実はこの記号は「シグニチャ」と言って、サービス・プログラムのレベルを確認するためのものなんです。
いわゆる Java や C++ などでいう”シグネチャ”と同じですね。

今度はサービス・プログラムの属性を DSPSRVPGM コマンドを使用して見てみましょう。

DSPSRVPGM SRVPGM(PROCTEST/MATH) DETAIL(*SIGNATURE) とコマンドを実行します。

元々、FACTORIAL と PERM というサブプロシージャのみが含まれていた時点でのシグニチャは実は↓のようになっていました。
プログラムの情報にあったものと一致していることがわかりますね。

FACTORIAL と PERM というサブプロシージャに加え、COMB サブプロシージャを追加して作成したサービス・プログラムについて、同じ情報を見てみると、全然違う記号になっているのがわかります。

Java や C++ などでいう”シグネチャ”というのは、ご存知の方も多いと思いますが、そのメソッド(関数)が受け入れるパラメータ/引数の組み合わせのことですね。
メソッド名が同じでも、受けとる引数のデータ型と数、順番が異なっていれば別のメソッドなわけで、C の関数でも ILE RPG のプロシージャでも同じ考えがなりたつわけです。

サービス・プログラムでは受け入れ可能なサブプロシージャのリスト/組み合わせを”シグネチャ”としているんですね。
同一のサービスプログラムかどうか、同じレベルかどうかの確認に使っている、ということです。

※ちなみに、Java のメソッドなどは同じシグネチャでオーバーライドができるようになっていますが、サービス・プログラムでも同じようなことが可能にはなっています。

同じプロシージャを含んでいるサービスプログラムを複数個、BNDSRVPGMパラメータに記述して CRTPGMすることは可能なのですが(OPTION(*DUPPROC)指定時)、そんな場合はこの”シグネチャ”が一致しているものが選ばれて実行されるようになっています。

では、以前のプログラムと今回のプログラムを両方サポートできるようにするにはどうしたらいいのでしょうか??

以前のプログラムと新しいプログラムを両方サポートするには

実は STRPGMEXP に PGMLVL というパラメータがあり、ここに *PRV と指定することができます。
つまり、前のレベルのシグネチャを共存させることができるようになっているんですね。

このソースでサービス・プログラムを作りなおしてみましょう。

作成コマンドは同じです。

作成されたサービス・プログラムの情報を見てみましょう。

DSPSRVPGM SRVPGM(PROCTEST/MATH) DETAIL(*SIGNATURE) とコマンドを実行します。

前回のものと、今回の新しいモジュールを追加したあとのものと、両方の「記号」が並存していることが確認できますね。

これで、前回のプログラムも今回のプログラムも両方ともエラーなしに動くようになりました。

[Top Pageに戻る]

Ads by TOK2