RPG ネイティブ・メソッド

RPG ネイティブ・メソッドを定義するには、通常の Java(TM) メソッドの場合にプロトタイプをコーディングするのと同じ方法でプロトタイプをコーディングします。それから、通常どおりに RPG サブプロシージャーを書きます。ネイティブ・メソッドの場合、 プロシージャー開始仕様書で EXPORT キーワードをコーディングする必要があります。

ネイティブ・メソッドは、ライブラリー・リストにあるサービス・プログラムの中に置かなければなりません。 ネイティブ・メソッドを呼び出している Java クラスに、次のような静的ステートメントがなければなりません。

          static
       {
            System.loadLibrary ("MYSRVPGM");
       }

これにより、Java はユーザーのネイティブ・メソッドを見つけることができます。*JAVA およびクラスを、ネイティブ・メソッドのプロトタイプのために EXTPROC キーワードに追加するのを除き、ユーザーは任意のサブプロシージャーと同じようにネイティブ・メソッドを書きます。図 83 は、ネイティブ・メソッドを呼び出す Java クラスの例です。

注意:
JVM の開始方法を制御するために環境変数を使用している場合は、 RPG プログラムが Java メソッドを呼び出す前に環境変数がジョブに存在している必要があります。 ADDENVVAR LEVEL(*SYS) を使用すると、環境変数はシステム・レベルで追加され、 デフォルトでは、各ジョブはその環境変数を設定した状態で開始されます。 これを行う場合は、システム上のアプリケーションが必要とする Java クラスを含むすべてのディレクトリーがクラスパスに含まれていることを確認してください。

図 83. ネイティブ・メソッドを呼び出す Java クラス
       class MyClass
       {

          static
          {
            System.loadLibrary ("MYSRVPGM");
          }

         native boolean checkCust (byte custName[]);

          void anotherMethod ()
          {
             boolean found;
             // call the native method
             found = checkCust (str.getBytes());
           }
        }

図 84 は RPG ネイティブ・メソッドのプロトタイプです。

図 84. RPG ネイティブ・メソッド・プロトタイプ
D checkCust       PR              N   EXTPROC(*JAVA
D                                           : 'MyClass'
D                                           : 'checkCust')
D   custName                   100A   VARYING CONST

ネイティブ・メソッド自身も他の任意のサブプロシージャーと同様にコーディングされます。図 85 は、RPG でコーディングされたネイティブ・メソッドの例です。

図 85. RPG でコーディングされたネイティブ・メソッドの例
P checkCust       B                   EXPORT
D checkCust       PI              N
D   custName                   100A   VARYING CONST
 /free   chain custName  rec;
   return %found;
  /end-free
P checkCust       E      

Java はユーザーのサービス・プログラムをデフォルトの活動化グループから呼び出します。ユーザーのサービス・プログラムが活動化グループ *CALLER を指定して作成されている場合は、そのサービス・プログラムはデフォルトの活動化グループで実行されることになります。 これは、次のような問題を招く場合があります。

ユーザーが自分のネイティブ・メソッド内に Java オブジェクトを作成する場合、デフォルトではそれらはネイティブ・メソッドの戻りの時点で Java によって破棄されます。 ネイティブ・メソッドの戻りの後もそれらのオブジェクトを使用したい場合 (例えば、後で別のネイティブ・メソッドから使用したい場合など) は、JNI ラッパー・プロシージャー getNewGlobalRef を呼び出すことにより、Java にグローバル参照を行ないたいことを伝える必要があります。グローバル参照を終えたら、JNI ラッパー・プロシージャー freeGlobalRef を呼び出せば、Java がそのオブジェクトを再利用することができます。これらのラッパー・プロシージャーについての 詳細は、オブジェクトを永続にしたいことを Java に伝えるおよび 永続オブジェクトの使用が終了したことを Java に伝えるを参照してください。

RPG ネイティブ・メソッドが処理できない例外で異常終了した時は、RPG コンパイラーは例外を Java に投げます。例外はクラス java.lang.Exception となり、RPG nnnnn という形式になります。 ここで、nnnnn は RPG 状況コードです。

              try
              {
                 nativeMethod ();
              }
              catch (Exception exc)
              {
                 ...
              }

非静的ネイティブ・メソッドにおけるインスタンス・パラメーターの入手

非静的ネイティブ・メソッドが呼び出される場合、Java がネイティブ・メソッドに渡すパラメーターのいずれかは、このメソッドが適用されるオブジェクトになります。これは「インスタンス・パラメーター」と呼ばれ、Java メソッドの中では「this」として参照されます。ネイティブ・メソッド自身の中で、組み込み関数 %THIS を使用してインスタンス・パラメーターを入手することができます。このパラメーターをユーザーの 「プロシージャー・インターフェース」の中にコーディングしてはなりません。

Java からネイティブ・メソッドへの文字パラメーターの受け渡し

文字パラメーターを扱う場合には、次の 2 つの選択肢があります。

RPG におけるストリング・オブジェクトの使用

RPG コードの中に String オブジェクトがある場合、図 86 にあるコーディングを使用してその長さと内容を検索することができます。

図 86. String オブジェクトの長さと内容を Java から検索する
D stringBytes     PR           100A   VARYING
D                                     EXTPROC(*JAVA
D                                           : 'java.lang.String'
D                                           : 'getBytes')
D stringLength    PR                  like(jint)
D                                     EXTPROC(*JAVA
D                                           : 'java.lang.String'
D                                           : 'length')
D string          S                   like(jstring)
D len             S                   like(jint)
D data            S            100A   VARYING
 /free      len = stringLength (string);
      data = stringBytes (string);
      if (len > %len(data));
            error ('Actual string was too long');
        endif;
  /end-free

ユーザーは、getBytes メソッドからの戻り値を、Java String の中にあるデータの長さについてユーザー自身が知っていることに基づいて長さを選んで、任意の長さ (可変または非可変のいずれでも) の文字データとして定義することができます。また、String オブジェクトの形式が正しいことが確実であれば、戻り値を Date、Time または Timestamp として定義することもできます。

他の方法として、getBytes の代わりに getChars メソッドを呼び出して、ストリング値を UCS-2 値として検索することもできます。