ファイヤープロジェクト
オブジェクトの生成
2003-07-20T15:13+09:00   matsu
ネイティブコードでもnewに相当することができる.
オブジェクトを生成する関数には,以下がある.
NewObject
もっとも簡単で標準的なメソッド生成関数.
NewObjectA
NewObjectとの違いは,コンストラクタへの引数をjavalueの配列で渡す点である.
NewObjectV
NewObjectとの違いは,コンストラクタへ可変個の引数を渡す点である.
AllocObject
オブジェクトのためにメモリを確保,割り付けるが,コンストラクタを実行しない.あとでコンストラクタを呼ぶには,通常のメソッドと同様にして呼ぶ.
これらはどれも以下の三つの引数を取る.
jclassの値
オブジェクト生成関数がクラスを識別するのに使用する.これで識別されたクラスのインスタンスが生成される.
jmethodIDの値
オブジェクト生成関数がコンストラクタを指定するのに使用する.
引数の一覧
コンストラクタが引数を取る場合,ここで引数を指定する.
また,Cの場合は例によってJNIEnvへのポインタも引数として必要である.以降で各メソッドについての説明とサンプルを示す.
NewObjectはもっとも簡単で標準的なメソッド生成関数である.
jobject (JNICALL *NewObject)
      (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
可変長引数(...)の部分がコンストラクタへの引数の一覧である.NewObjectを使用するサンプルを示す.このサンプルは以下のクラスのコンストラクタをネイティブメソッド内で呼び出す.
そのネイティブメソッドを以下のクラスで宣言する.
そしてネイティブメソッド.
コメントにあるように,コンストラクタのメソッド名は常に<init>である.また,生成するオブジェクトのjclass値を取得するのを忘れないようにする(実はこれでちょっとハマった).実行結果を以下に示す.
instanceof : true
comment : Constructed with no parameter
instanceof : true
comment : Constructed with hoge and 999
なお,ここで使用したFindClassはクラス名を示す文字列からjclassを取得する関数である.
jclass (JNICALL *FindClass)
      (JNIEnv *env, const char *name);
NewObjectAは,コンストラクタへの引数をjvalueの配列に格納して呼び出す.
jobject (JNICALL *NewObjectA)
      (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args);
jvalueは全てのネイティブ型を格納できる共用体である.
typedef union jvalue {
    jboolean z;
    jbyte    b;
    jchar    c;
    jshort   s;
    jint     i;
    jlong    j;
    jfloat   f;
    jdouble  d;
    jobject  l;
} jvalue;
NewObjectAを使用するサンプルを示す.このサンプルは先のサンプルと同じSampleObjectをネイティブメソッドの中からNewObjectAを使用して生成するものである.まず,ネイティブメソッドを宣言し呼び出すクラス.
先のサンプルとほとんど同じである.次にネイティブメソッド.
上のように,引数のないコンストラクタをNewObjectAで呼ぶときはargsにNULLを指定する.実行結果は先のサンプルと同じである.
NewObjectVは,コンストラクタへの引数として可変個の引数を指定することができる.
jobject (JNICALL *NewObjectV)
      (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
この関数はネイティブコードでオブジェクト生成のための補助関数を作成するのに便利な関数である.その便利さを示すサンプルを示す.このサンプルは最初のサンプルと同じSampleObjectをネイティブメソッドの中からNewObjectVを使用して生成するものである.まず,ネイティブコードを宣言し,呼び出すクラス.
先のサンプルとほとんど同じである.次にネイティブメソッド.
このように,NewObjectVは似たような働きをするオブジェクトを共通化したりするのに便利である.なお,実行結果は先のサンプルと同じである.
これまでのNewObject?は,コンストラクタを呼び出してオブジェクトを生成するものであった.このとき,おそらく
  • メモリの割り当て
  • コンストラクタによるオブジェクトの初期化
が行なわれていると考えられるが,AllocObjectは,前者のみを実行するものである.
jobject (JNICALL *AllocObject)
      (JNIEnv *env, jclass clazz);
これによって返されるjobjectは,初期化されていない.ただ,メモリの割り当てを行なわれただけの状態である.どういうときに使うと有益なのかちょっと思い付かないが,とにかくAllocObjectを使用するサンプルを示す.このサンプルは最初のサンプルと同じSampleObjectをネイティブメソッドの中からAllocObjectとコンストラクタ呼び出しを使用して生成するものである.まず,ネイティブコードを宣言し,呼び出すクラス.
先のサンプルとほとんど同じである.次にネイティブメソッド.
このように,AllocObjectを使用する場合は,別途CallVoidMethodでコンストラクタを実行する必要がある.どのような時に使用するのがよいかは良く分からないが,頭の片隅においておいて損はなかろう.
matsu(C)
Since 2002
Mail to matsu