perlmroapi - Perl メソッド解決プラグインインターフェース
Perl 5.10.1 から、デフォルト(深さ優先線形検索)以外のメソッド解決順序を プラグインとして使うための新しいインターフェースがあります。 5.10.0 で追加された C3 メソッド解決順序は、Perl 側のインターフェースを 変更することなくプラグインとして再実装されました。
それぞれのプラグインは以下の構造体を提供することで自分自身を登録します
struct mro_alg {
AV *(*resolve)(pTHX_ HV *stash, U32 level);
const char *name;
U16 length;
U16 kflags;
U32 hash;
};
そして Perl_mro_register
を呼び出します:
Perl_mro_register(aTHX_ &my_mro_alg);
後述する線形化関数へのポインタ
MRO の名前 (ISO-8859-1 か UTF-8 のどちらか)。
名前の長さ。
名前が UTF-8 で与えられた場合、これを HVhek_UTF8
に設定します。 この値は hv_common()
の kflags に直接渡されます。
MRO 名のための事前に計算されたハッシュ値、または 0。
resolve
関数は、与えられたスタッシュのための線形化された ISA を この MRO を使って生成するために呼び出されます。 これはスタッシュへのポインタおよび、0 を入れた level で呼び出されます。 この関数を呼び出すときにはコアは常に level に 0 を設定します - この引数は再帰が必要なときに深さを記録できるようにします。
関数は親クラスを並べたものが入った配列へのリファレンスを返します。 クラスの名前はスタッシュに対して HvENAME()
を呼び出した結果です。 そのような場合で HvENAME()
が null を返すと、HvNAME()
が代わりに 使われます。
呼び出し元は、構造体を保持したいなら返された配列の参照カウントを インクリメントする責任を負います。 従って、ポインタで指していない一時的な値を作った場合、正しく捨てられるために sv_2mortal()
します。 返り値をキャッシュする場合、参照カウントを変更することなくポインタを 返します。
MRO の計算は高く付くことがあります。 実装は、単一の SV *
、または AV *
のような SV *
にキャッシュできる もののキャッシュを提供します。 プライベートな値を読み込むには、 MRO_GET_PRIVATE_DATA()
マクロを使って、スタッシュと mro_alg
構造体への ポインタから mro_meta
構造体を渡します:
meta = HvMROMETA(stash);
private_sv = MRO_GET_PRIVATE_DATA(meta, &my_mro_alg);
プライベートな値を設定するには、Perl_mro_set_private_data()
を 呼び出します:
Perl_mro_set_private_data(aTHX_ meta, &c3_alg, private_sv);
プライベートデータキャッシュは private_sv へのリファレンスの所有権を 取ります; hv_store()
が渡された値へのリファレンスの所有権を取るのと 同様です。
MRO 実装の例については、ext/mro/mro.xs の S_mro_get_linear_isa_c3()
と BOOT:
の節、および mro_core.c の S_mro_get_linear_isa_dfs()
を 参照してください。
C3 MRO と perl コア内の切り替え可能な MRO の実装は Brandon L Black によって 書かれました。 Nicholas Clark はプラグイン可能なインターフェースを作成し、これで動くように Brandon の実装をリファクタリングし、この文書を書きました。