RPG IV コンパイラーの Java(TM) メソッド呼び出しのサポート、および RPG ネイティブ・メソッドの作成のサポートでは、ほとんどすべての JNI コーディングは、RPG プログラマーからは見えません。ただし、RPG のサポートが最も効果的であるとは限りません。例えば、RPG は 呼び出しの時およびネイティブ・メソッドの入り口と出口において必ず、RPG と Java との間の配列の変換を行ないますが、パフォーマンスを向上させるにはユーザー自身で配列の変換を行なった方がよい場合もあります。
RPG のサポートは、ユーザーに Java メソッドへのアクセスを提供しているに過ぎません。 クラスの中のフィールドにアクセスしたい場合は Java クラスに対して「入手」メソッドと「設定」メソッドを追加するか、または JNI コーディングをすることが必要になります (Java クラスの中のフィールドへのアクセス を参照)。
図 92 は、RPG における JNI 呼び出しの例です。
/COPY JNI
D objectId s like(jobject)
D methodId s like(jmethodID)
D string s like(jstring)
D parms s like(jvalue) dim(2)
/free
jvalue_P = %addr(parms(1));
jvalue.i = 10;
jvalue_P = %addr(parms(2));
jvalue.l = string;
CallVoidMethodA (JNIEnv_P : objectId : methodId : parms);
/end-free
ポインター JNIEnv_P およびポインター jvalue_P は JNI /COPY ファイルの中で定義されていることに注意してください。
Java では、文字データは EBCDIC ではなく ASCII であるため、FindClass などの JNI 機能を呼び出すには、クラス名、メソッド名、およびフィールド名は必ず ASCII にしておく必要があります。Java から来る文字データも ASCII なので、これをユーザーの RPG プログラムの中で使用するには、おそらく EBCDIC への変換をすることになります。RPG コンパイラーはこれらの変換をユーザーに代わって行ないますが、ユーザー自身が JNI 呼び出しを行なう場合は ASCII と EBSDIC 間の変換を行なう必要があります。
RPG がサポートするのは Java メソッドの 呼び出しのみです。Java フィールドへの アクセスはサポートしません。通常、フィールドは「get」メソッドおよび「set」メソッドを通じて アクセスされますが、JNI 呼び出しを使用してフィールドにアクセスすることも可能です。ここでは、 Java クラスまたはオブジェクトのフィールドへのアクセスに必要な JNI 呼び出しの例を示します。
*------------------------------------------------------------------ * この例は、クラスまたはオブジェクトのフィールドにアクセスするための * JNI の使用法を示しています。 * * このプログラムは Rectangle オブジェクトを作成し、JNI 呼び出しを * 使用して、width 変数と height 変数に直接アクセスします。 * * この特定の例においては、getWidth()、getHeight、 * setWidth() および setHeight() メソッドを使用して * これらのフィールドにアクセスし、JNI 呼び出しの使用は避けます。 *------------------------------------------------------------------ H THREAD(*SERIALIZE) /DEFINE JNI_COPY_FIELD_FUNCTIONS /COPY JNI /COPY JNIRPG_PR *------------------------------------------------------------------ * JAVA クラスおよびメソッド *------------------------------------------------------------------
D Rectangle C 'java.awt.Rectangle' D NewRectangle PR O EXTPROC(*JAVA D : Rectangle D : *CONSTRUCTOR) D x 10I 0 VALUE D y 10I 0 VALUE D width 10I 0 VALUE D height 10I 0 VALUE *------------------------------------------------------------------ * JAVA 名の ASCII 表記を用いた定数 *------------------------------------------------------------------ * これらの値を判別する 1 つの方法は、文字値を UCS-2 に変換するために * %UCS2 を使用して、結果をデバッガーの中で * 16 進で表示するという方法です。 * * ASCII 値は UCS-2 文字に 2 バイトおきに入っています。 * * 例えば、%UCS2('abc') = X'006100620063' * -- -- -- * 'abc' の ASCII 表記は X'616263' です。 *------------------------------------------------------------------ D ASCII_I C x'49' D ASCII_x C x'78' D ASCII_y C x'79' D ASCII_width C X'7769647468' D ASCII_height C X'686569676874' * JNI はスラッシュを区切り文字として使用するため、これは *「java/awt/Rectangle」であって「java.awt.Rectangle」ではないことに注意。 D ASCII_Rectangle... D C X'6A6176612F6177742F52656- D 374616E676C65' *------------------------------------------------------------------ * 取り消し処理 *------------------------------------------------------------------ D EnableCanHdlr PR EXTPROC('CEERTX') D Handler * CONST PROCPTR D CommArea * CONST OPTIONS(*OMIT) D Feedback 12A OPTIONS(*OMIT) D CanHdlr PR D CommArea * CONST *------------------------------------------------------------------ * 変数およびプロシージャー *------------------------------------------------------------------ D rect s O CLASS(*JAVA : Rectangle) D x S 10I 0 D y S 10I 0 D rectClass S LIKE(jclass) D fieldId S LIKE(jfieldID) D msg S 52A D Cleanup PR *------------------------------------------------------------------ * 取り消し処理プログラムを使用可能にし終結処理が完了したことを確認 *------------------------------------------------------------------ C CALLP EnableCanHdlr (%PADDR(CanHdlr) C : *OMIT : *OMIT) *------------------------------------------------------------------ * x,y 座標 (5, 15) を使用して、幅 100 で高さが 200 の * 新しい Rectangle を作成します。 *------------------------------------------------------------------ C EVAL rect = NewRectangle (5 : 15 : 100 : 200) *------------------------------------------------------------------ * Rectangle のフィールドにアクセスするための JNI 機能を呼び出す準備 *------------------------------------------------------------------
C EVAL JNIEnv_P = getJniEnv () C EVAL rectClass = FindClass (JNIEnv_P C : ASCII_Rectangle) *------------------------------------------------------------------ * Rectangle の幅および高さを検索するための JNI 機能の呼び出し *------------------------------------------------------------------ C eval fieldId = GetFieldID (JNIEnv_P C : rectClass C : ASCII_width C : ASCII_I) C eval width = GetIntField (JNIEnv_P C : rect C : fieldId) C eval fieldId = GetFieldID (JNIEnv_P C : rectClass C : ASCII_height C : ASCII_I) C eval height = GetIntField (JNIEnv_P C : rect C : fieldId) C eval msg = 'The rectangle has dimensions (' C + %trim(%editc(width : '1')) C + ', ' C + %trim(%editc(height : '1')) C + ')' C msg dsply *------------------------------------------------------------------ * Cleanup プロシージャーを呼び出します。 *------------------------------------------------------------------ C callp Cleanup() C eval *INLR = '1' *------------------------------------------------------------------ * Cleanup。* - 必要であればオブジェクトを解放します。 *------------------------------------------------------------------ P Cleanup B C if rect <> *NULL and C JNIEnv_P <> *NULL C callp DeleteLocalRef(JNIEnv_P : rect) C endif C eval rect = *NULL C eval JNIEnv_P = *NULL P Cleanup E *------------------------------------------------------------------ * 取り消し処理プログラム。終結処理が完了したことを確認。 *------------------------------------------------------------------ P CanHdlr B D CanHdlr PI D CommArea * CONST C callp Cleanup() P CanHdlr E
最初の 3 つのパラメーターは、必ず次と同じになります。
メソッド固有のパラメーターは、これら 3 つのパラメーターの後に、3 つの異なる方法のいずれかでコーディングされます。例えば、メソッドが値を戻さない場合 (戻りタイプは「void」)。
void mymethod (int len, String str) の場合、CallVoidMethod 用に以下のプロトタイプをコード化することができます。
D CallMyMethod PR EXTPROC(*CWIDEN D : JNINativeInterface. D CallVoidMethod_P) D env LIKE(JNIEnv_P) VALUE D obj LIKE(jobject) VALUE D methodID LIKE(jmethodID) VALUE D len LIKE(jint) VALUE D str LIKE(jstring) CONST D dummy 1a OPTIONS (*NOPASS) ... CallMyMethod (JNIEnv_P : objectId : methodId : 10 : string);
実際にどの機能を呼び出すかは、戻り値のタイプによって決まります。例えば、メソッドが整数を戻す場合であれば、 CallIntMethodA を使用することになります。これらの機能のクラスおよび methodID パラメーターを入手するには、FindClass と GetMethodID または GetStaticMethodID を使用します。
(C) Copyright IBM Corporation 1992, 2006. All Rights Reserved.