RPG ネイティブ・メソッドを定義するには、通常の Java(TM) メソッドの場合にプロトタイプをコーディングするのと同じ方法でプロトタイプをコーディングします。それから、通常どおりに RPG サブプロシージャーを書きます。ネイティブ・メソッドの場合、 プロシージャー開始仕様書で EXPORT キーワードをコーディングする必要があります。
ネイティブ・メソッドは、ライブラリー・リストにあるサービス・プログラムの中に置かなければなりません。 ネイティブ・メソッドを呼び出している Java クラスに、次のような静的ステートメントがなければなりません。
static { System.loadLibrary ("MYSRVPGM"); }
これにより、Java はユーザーのネイティブ・メソッドを見つけることができます。*JAVA およびクラスを、ネイティブ・メソッドのプロトタイプのために EXTPROC キーワードに追加するのを除き、ユーザーは任意のサブプロシージャーと同じようにネイティブ・メソッドを書きます。図 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 ネイティブ・メソッドのプロトタイプです。
D checkCust PR N EXTPROC(*JAVA D : 'MyClass' D : 'checkCust') D custName 100A VARYING CONST
ネイティブ・メソッド自身も他の任意のサブプロシージャーと同様にコーディングされます。図 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 を使用してインスタンス・パラメーターを入手することができます。このパラメーターをユーザーの 「プロシージャー・インターフェース」の中にコーディングしてはなりません。
文字パラメーターを扱う場合には、次の 2 つの選択肢があります。
RPG コードの中に String オブジェクトがある場合、図 86 にあるコーディングを使用してその長さと内容を検索することができます。
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 値として検索することもできます。
(C) Copyright IBM Corporation 1992, 2006. All Rights Reserved.