dump
関数で調べるperlguts - Perl API の紹介
このドキュメントでは Perl API の使い方、および Perl コアの基本的な動作に 関するいくばくかの情報を提供しようとしています。 完璧からは程遠いものですし、間違いも多いと思います。 疑問点やコメントは後述する著者に対して行なってください。
Perl では、主となる三つのデータ型を扱うために三つの型定義を行なっています:
SV Scalar Value
AV Array Value
HV Hash Value
それぞれの typedef には様々なデータ型を操作するための特別なルーチンが 用意されています。
Perl では、符号付き整数でもポインタでも十分に入れることのできる特別な typedef である IV を使います。 更に、単に符号なしの IV である UV もあります。
Perl はまた、二つの特殊な typedef である I32 と I16 を使っています。 これらはそれぞれ、常に最低 32bit、16bit の長さを持っているものです。 (再び、同様に U32 と U16 もあります。) これらは普通は正確に 32 ビットと 16 ビットですが、Cray では両方とも 64 ビットです。
SV は、1 つのコマンドで生成し、値をロードすることができます。 ロードできる値の型には、整数 (IV)、符号なし整数 (UV)、 倍精度 (NV)、文字列 (PV)、その他のスカラ (SV) があります。
これらを行なう、7 つのルーチンは:
SV* newSViv(IV);
SV* newSVuv(UV);
SV* newSVnv(double);
SV* newSVpv(const char*, STRLEN);
SV* newSVpvn(const char*, STRLEN);
SV* newSVpvf(const char*, ...);
SV* newSVsv(SV*);
STRLEN
は perl が扱えるどんな文字列のサイズも表現するのに十分なだけの 大きさを持つことが保証されている整数型(Size_t, 普通は config.h で size_t として定義されています)。
あまりなさそうですが、SV がもっと複雑な初期化を必要とする場合、 newSV(len) で空の SV も作成できます。 もし len
が 0 なら、NULL 型の空の SV が返され、さもなければ PV 型の SV は、SvPVX でアクセスできる len + 1 (NUL のため) バイトの領域を 割り当てられて返されます。 両方の場合で、SV の値は未定義値です。
SV *sv = newSV(0); /* no storage allocated */
SV *sv = newSV(10); /* 10 (+1) bytes of uninitialised storage allocated */
既に存在する スカラの値を変更するために 8 つのルーチンがあります:
void sv_setiv(SV*, IV);
void sv_setuv(SV*, UV);
void sv_setnv(SV*, double);
void sv_setpv(SV*, const char*);
void sv_setpvn(SV*, const char*, STRLEN)
void sv_setpvf(SV*, const char*, ...);
void sv_vsetpvfn(SV*, const char*, STRLEN, va_list *, SV **, I32, bool *);
void sv_setsv(SV*, SV*);
代入すべき文字列の長さを sv_setpvn
や newSVpv
、あるいは newSVpv
を使って指定することもできますし、sv_setpv
を使ったり newSVpv
の第二引数に 0 を指定することによって、Perl 自身に 文字列の長さを計算させることもできます。 ただし Perl は、NUL 文字で終了することに依存している strlen
を使って長さを計算しているということに注意してください。
sv_setpvf
の引数は sprintf
と同じように処理され、書式化された 出力が値となります。
sv_vsetpvfn
は vsprintf
と同じようなものですが、 可変引数リストに対するポインタか SV の配列のアドレスと長さのいずれかを指定することができます。 最後の引数はブール値を指し示します。 関数から返ってきたときに これが true であれば、フォーマット文字列としてロカール固有の 情報が使われているのでその文字列の内容は信頼するできないことを 表わしています(perlsec を参照)。 ロカールに関する情報が重要でないのなら、 このポインタは NULL であってもかまいません。 この関数はフォーマットの長さを要求していることに注意してください。
sv_set*()
関数群は“magic”を持っている値に対する 操作に対して充分に一般化されたものではありません。 後述する "Magic Virtual Tables" を参照してください。
すべてのSV は、必須と言うわけではありませんが NUL キャラクターで 終端されているべきです。 この終端の NUL が無かった場合、コアダンプしたり文字列を (文字列が NUL で終端されていることを期待している) C 関数やシステムコールに 渡すコードをおかしくする危険があります。 Perl 自身の典型的な関数は、この理由により終端に NUL を追加します。 そうであったとしても、あなたが SV に格納されている文字列を C の関数や システムコールに渡す時には十二分に気をつけるべきなのです。
SV が指し示す実際の値をアクセスするには、以下のマクロを使えます:
SvIV(SV*)
SvUV(SV*)
SvNV(SV*)
SvPV(SV*, STRLEN len)
SvPV_nolen(SV*)
これは実際のスカラの型を自動的に IV や UV や倍精度や文字列にします。
SvPV
マクロでは、返される文字列の長さは、変数 len
に格納されます (これはマクロですから、&len
と しないで ください)。 もしデータの長さを気にしないのであれば、SvPV_nolen
マクロを 使ってください。 歴史的に、この場合にはグローバル変数 PL_na
に SvPV
マクロが 使われてきました。 しかしこれは可能ですが効率は良くありません; なぜなら PL_na
はスレッド化した Perl ではスレッドローカルな 領域にアクセスしなければならないからです。 いずれの場合にも、Perl は NUL を含んでいる文字列と NUL で 終端されていないような文字列の両方を扱うことができるということを 覚えておいてください。
同様に、Cで foo(SvPV(s, len), len);
とすることが安全ではないことを 忘れないでください。 これはあなたの使うコンパイラによってはうまくいきますが、 いつでもそうだとは限らないのです。 そこで、こういったステートメントは以下のように分割します:
SV *s;
STRLEN len;
char * ptr;
ptr = SvPV(s, len);
foo(ptr, len);
単にスカラ値が真かどうかを知りたいだけならば、
SvTRUE(SV*)
Perl は、SV にもっとメモリを割り当てて欲しいときには自動的に文字列を 大きくしてくれますが、さらにメモリを割り当てさせることが必要であれば
SvGROW(SV*, STRLEN newlen)
というマクロが使えます。 もし必要なら、このマクロが sv_grow
を呼びます。 SvGROW
は SV に割り当てたメモリを増やすだけで、減らすことは できないということと、終端の NUL の分のバイトが自動的に加算されない (perl自身の文字列関数は 大概 SvGROW(sv, len + 1)
としています)と いうことに注意してください。
手元にある SV の、 Perl から見たデータの種類を知りたいときには、 その SV の型をチェックするのに
SvIOK(SV*)
SvNOK(SV*)
SvPOK(SV*)
SV に納められた文字列の現在の長さを取得したり設定したりするのに は以下のマクロが使えます。
SvCUR(SV*)
SvCUR_set(SV*, I32 val)
同様に、SV に格納されている文字列の終端へのポインタを以下のマクロを 使って得ることができます。
SvEND(SV*)
ただし、これらは SvPOK()
が真のときだけ有効だということに気を つけてください。
SV*
に格納されている文字列の末尾になにかを追加したいときに以下のような 関数が使えます。
void sv_catpv(SV*, const char*);
void sv_catpvn(SV*, const char*, STRLEN);
void sv_catpvf(SV*, const char*, ...);
void sv_vcatpvfn(SV*, const char*, STRLEN, va_list *, SV **, I32, bool);
void sv_catsv(SV*, SV*);
最初の関数は strlen
を使って追加する文字列の長さを計算します。 二番目の関数では、関数を使用する人が文字列の長さを指定します。 三番目の関数はその引数を sprintf
の様に処理し、整形された結果を 追加します。 四番目の関数は vsprintf
のように動作します。 va_list 引数の代わりに、SV の配列のアドレスと長さを指定することが できます。 五番目の関数は最初の SV にある文字列を二番目の SV にある文字列で 拡張します。 また、この関数は二番目の SV を強制的に文字列として解釈します。
sv_cat*()
関数群は“magic”を持っている値に対する 操作に対して充分に一般化されたものではありません。 後述する "Magic Virtual Tables" を参照してください。
スカラ変数の名前がわかれば、その SV へのポインタは以下のようにして 得られます:
SV* get_sv("package::varname", FALSE);
これは変数が存在していない場合には NULL を返します。
その変数 (もしくは他の任意の SV) が、実際に 定義されているか を 知りたいならば、
SvOK(SV*)
スカラの undef
値は、PL_sv_undef
という SV のインスタンスに 納められています。
そのアドレスは、SV*
が必要とされるところで使用することができます。 任意の sv を &PL_sv_undef
を比較しようとしないように気をつけてください。 例えば、Perl コードとのインターフェースで、以下は正しく動きます:
foo(undef);
しかし、以下のように呼び出すと動作しません:
$x = undef;
foo($x);
従って、sv が定義されているかをチェックするために、毎回繰り返して SvOK() を使ってください。
また、AV や HV の値として &PL_sv_undef
を使うときにも 注意しなければなりません ("AVs, HVs and undefined values" を 参照してください)。
ブール値の真と偽を表わす、PL_sv_yes
や PL_sv_no
という値もあります。 PL_sv_undef
と同様に、これらのアドレスも SV*
が必要なところで 使うことができます。
(SV *0)
と &PL_sv_undef
が同じであると考えて、だまされてはいけません。 次のようなコードを見てください:
SV* sv = (SV*) 0;
if (I-am-to-return-a-real-value) {
sv = sv_2mortal(newSViv(42));
}
sv_setsv(ST(0), sv);
このコードは、実値を返さなければならないときには、(値として 42 を 持つ) 新しい SV を返そうとし、さもなくば undef を返そうとします。 ですが、どこかの行でヌルポインタを返して、セグメントバイオレーションが 起こるか、何かおかしな結果になってしまいます。 最初の行の 0 を &PL_sv_undef
に変えれば、すべてがうまくいきます。
生成した SV を解放するためには、SvREFCNT_dec(SV*)
を呼びます。 普通は、この呼び出しは必要ありません。 "Reference Counts and Mortality" を参照してください。
Perl は文字列の先頭から効率的に文字を削除するための関数 sv_chop
を 提供されています; これに SV と、PV の内側のどこかへのポインタを渡すと、 そのポインタより手前の全てを削除します。 効率性はちょっとしたハックによるものです: 実際に文字を削除する代わりに、 sv_chop
は、他の関数にオフセットハックが有効であることを示す OOK
(offset OK) フラグを設定して、SV の IV フィールドに、切り落とすバイト数を 設定します。 それから(SvPVX
と呼ばれる)PV ポインタを移動させて、SvCUR
と SvLEN
を調整します。
従って、この時点で、割り当てられたバッファの先頭はメモリ中の SvPVX(sv) - SvIV(sv)
であり、PV ポインタは割り当てられた保管領域の中間を 指しています。
これは例による最良の実演です:
% ./perl -Ilib -MDevel::Peek -le '$a="12345"; $a=~s/.//; Dump($a)'
SV = PVIV(0x8128450) at 0x81340f0
REFCNT = 1
FLAGS = (POK,OOK,pPOK)
IV = 1 (OFFSET)
PV = 0x8135781 ( "1" . ) "2345"\0
CUR = 4
LEN = 5
ここで切り落とされたバイト数 (1) は IV に設定され、Devel::Peek::Dump
は これがオフセットであることを示す助けをしてくれます。 「実際」と「偽物」の開始の間の文字列の部分はかっこで示され、 SvCUR
と SvLEN
の値は実際のものではなく偽物の先頭を反映します。
オフセットハックと似たようなものは、配列の先頭の効率的なシフトと切り落としを 有効にするために AV に対しても行われます; AvARRAY
は Perl から見える配列の最初の要素を指していますが、AvALLOC
は C の配列の実際の先頭を指しています。 これらは普通は同じですが、shift
演算子は AvARRAY
を一つ増やして、 AvFILL
と AvLEN
を一つ減らします。 再び、C の配列の実際の先頭の一は、配列を解放するときにだけ使われます。 av.c の av_shift
を参照してください。
自分で保持しているスカラの型を決定する通常の方法は、マクロ Sv*OK
を 使うものでした。 スカラは数値にも文字列にもなり得ますから、普通、 これらのマクロはいつも真を返します。 そして Sv*V
マクロを呼ぶことで、 文字列から整数/倍精度、整数/倍精度から文字列への変換を行ないます。
もし、本当に SV にあるのが整数か、倍精度か、文字列ポインタかを 知りたいのであれば、
SvIOKp(SV*)
SvNOKp(SV*)
SvPOKp(SV*)
というマクロを代わりに使うことができます。 これらのマクロは、実際に SV に入っているものが整数か、倍精度か、 文字列ポインタかを教えてくれます。 "p" はプライベートの意味です。
プライベートと公的なフラグが異なるのは様々な方法があります。 例えば、tie された SV は IV スロットに妥当な値を保持している (従って SvIOKp は真) かもしれませんが、データは直接ではなく FETCH ルーチンを 通してアクセスされるべきなため、SvIOK は偽です。 他の例としては数値変換が起こり、精度が落ちた場合です:プライベートな フラグのみが「精度が落ちた」値に設定されます。 それで、NV が精度が落ちる形で IV に変換されると、SvIOKp, SvNOKp, SvNOK は 設定されますが、SvIOK は設定されません。
しかし一般的には、Sv*V
マクロを使うだけにした方が良いでしょう。
AV を生成して値を設定するのには、二つの方法があります。 最初の方法は、単に空の AV を作るものです:
AV* newAV();
ふたつめの方法は、AV を生成した上で、初期値として SV の値を入れます:
AV* av_make(I32 num, SV **ptr);
二番目の引数は num 個の SV* の配列を指しています。 AV が生成されてしまえば、SV は(それを望むのなら)破棄することができます。
いったん AV が生成されると、AV に対して、
void av_push(AV*, SV*);
SV* av_pop(AV*);
SV* av_shift(AV*);
void av_unshift(AV*, I32 num);
といった操作が行えます。 これらは、av_unshift
を除いては、お馴染みの演算でしょう。 av_unshift
は、配列の先頭に num
個の undef
値の要素を付け加えます。 その後で、(後述する) av_store
を使って新しい要素に値を 代入しなければなりません。
他にもいくつか関数があります:
I32 av_len(AV*);
SV** av_fetch(AV*, I32 key, I32 lval);
SV** av_store(AV*, I32 key, SV* val);
関数 av_len
は配列における最高位の添え字を(ちょうど Perl の $#array と 同じように)返します。 もし配列が空であれば、-1 を返します。 関数 av_fetch
は添え字 key
の位置にある値を返しますが、lval
が 非ゼロであれば、av_fetch
はその位置に undef を格納しようとします。 関数 av_store
は添え字 key
の位置に値 val
を格納し、val
の 参照カウントをインクリメントしません。 従って、呼び出し側はこの振る舞いに注意して対処し、av_store
が NULL を返した場合には、メモリリークを防ぐために参照カウントの デクリメントを行う必要があるでしょう。 av_fetch
と av_store
の両方ともがその戻り値として SV*
ではなく、SV**
を返すということに注意してください。
void av_clear(AV*);
void av_undef(AV*);
void av_extend(AV*, I32 key);
関数 av_clear
は、配列 AV* にあるすべての要素を削除しますが、 配列自身の削除は行いません。 関数 av_undef
は配列にあるすべての要素に加え、配列自身の削除も行います。 関数 av_extend
は配列を key+1
要素だけ拡張します。 key+1
が配列のその時点での長さより短ければ、何も行なわれません。
配列変数の名前がわかっているのであれば、次のようにしてその配列に 対応する AV へのポインタが得られます:
AV* get_av("package::varname", FALSE);
これは変数が存在していない場合には NULL を返します。
tie された配列における配列アクセス関数の使い方についての詳細は "Understanding the Magic of Tied Hashes and Arrays" を参照してください。
HV を生成するには、
HV* newHV();
というルーチンを使います。 いったん HV が生成されると HV に対して、
SV** hv_store(HV*, const char* key, U32 klen, SV* val, U32 hash);
SV** hv_fetch(HV*, const char* key, U32 klen, I32 lval);
という操作が行えます。 引数 klen
は、渡される key の長さです (Perl にキーの長さを計算させるために、klen
の値として 0 を渡すことは できないということに注意してください)。 引数 val
は、設定されるスカラへの SV ポインタを入れ、hash は、 あらかじめ計算したハッシュ値 (hv_store
に計算させる場合には、 ゼロ) です。 引数 lval
で、このフェッチ操作が実はストア操作の一部であるかどうかを 示します。 ストア操作であれば、新たなundefind value が与えられた キーを伴って HV に追加され、hv_fetch
はその値が既に 存在していたかのようにリターンします。
hv_store
や hv_fetch
は、SV**
を返すもので、SV*
ではないことに 注意してください。 スカラ値をアクセスするには、まず戻り値の参照外し(dereference)をする 必要があります。 しかし、その前に返却値が NULL でないことを確認すべきです。
ハッシュテーブルのエントリが存在するかをチェックし、削除を行う 関数があります。
bool hv_exists(HV*, const char* key, U32 klen);
SV* hv_delete(HV*, const char* key, U32 klen, I32 flags);
flag
に G_DISCARD
フラグが含まれていなければ、hv_delete
は 削除された値の揮発性のコピー(mortal copy)を生成し、それを返します。
さらに様々な関数があります:
void hv_clear(HV*);
void hv_undef(HV*);
引数に AV を取る似たような関数と同様、hv_clear
はハッシュテーブルにある すべてのエントリーを削除しますがハッシュテーブル自身は削除しません。 hv_undef
はエントリーとハッシュテーブル自身の両方を削除します。
Perl は実際のデータを HE と typedef された構造体のリンクリストを使って 保持しています。 これらは実際のキーと値のポインタ(それに加えて管理のための ちょっとしたもの)を保持しています。 キーは文字列へのポインタであり、値は SV*
です。 しかしながら、一度 HE*
を持てば、実際のキーと値とを取得するためには 以下に挙げるようなルーチンを使います。
I32 hv_iterinit(HV*);
/* ハッシュテーブルをたどるための開始点を準備 */
HE* hv_iternext(HV*);
/* 次のエントリーを取得して、キーと値両方を持つ構造
体へのポインタを返す */
char* hv_iterkey(HE* entry, I32* retlen);
/* HE 構造体からキーを取得し、そのキー文字列の長さを
返す */
SV* hv_iterval(HV*, HE* entry);
/* HE 構造体の値に対する SV ポインタを返す */
SV* hv_iternextsv(HV*, char** key, I32* retlen);
/* この便利なルーチンは、hv_iternext、hv_iterkey、
hv_itervalを組み合わせたものです。
引数keyとretlenは、キーとその長さを表わす戻り値です。
関数の戻り値はSV* で返されます。*/
配列変数の名前がわかるのであれば、以下のようにしてその変数の HV への ポインタが得られます:
HV* get_hv("package::varname", FALSE);
これは変数が存在していない場合には NULL を返します。
ハッシュアルゴリズムは PERL_HASH(hash, key, klen)
というマクロで 定義されています。
hash = 0;
while (klen--)
hash = (hash * 33) + *key++;
hash = hash + (hash >> 5); /* after 5.6 */
最後のステップは、結果となるハッシュ値の低位ビットの分散を改良するために バージョン 5.6 で追加されました。
tie されたハッシュに対するハッシュアクセス関数の使い方に 関する詳細は、"Understanding the Magic of Tied Hashes and Arrays" を 参照してください。
バージョン 5.004 から、以下の関数がサポートされました。
HE* hv_fetch_ent (HV* tb, SV* key, I32 lval, U32 hash);
HE* hv_store_ent (HV* tb, SV* key, SV* val, U32 hash);
bool hv_exists_ent (HV* tb, SV* key, U32 hash);
SV* hv_delete_ent (HV* tb, SV* key, I32 flags, U32 hash);
SV* hv_iterkeysv (HE* entry);
これらの関数が、ハッシュ構造を扱うエクステンションの記述を単純にする SV*
キーを引数にとることに注意してください。 これらの関数はまた、SV*
キーを(先に挙げた関数群とは異なり) 文字列化することなしに tie
関数に渡すことを許しています。
これらの関数はまた、ハッシュエントリー全体 (HE*
) を返したり受け付けて、 より効率良く使用します(特定の文字列に対するハッシュ番号は 毎回計算しなおす必要はないからです)。 詳しくは perlapi を参照してください。
以下に挙げるマクロは、ハッシュエントリーの内容にアクセスするのに 常に使わなければならないものです。 これらのマクロはその引数を二度以上評価する可能性があるので、マクロに 対する引数は単純な変数でなければならないということに注意してください。 これらのマクロに関する詳細は perlapi を参照してください。
HePV(HE* he, STRLEN len)
HeVAL(HE* he)
HeHASH(HE* he)
HeSVKEY(HE* he)
HeSVKEY_force(HE* he)
HeSVKEY_set(HE* he, SV* sv)
低レベルマクロが二つ定義されていますが、これらは SV*
ではないキーを 扱うときにのみ使わなければならないものです。
HeKEY(HE* he)
HeKLEN(HE* he)
hv_store
と hv_store_ent
の両方ともが、val
に格納されている 参照カウントのインクリメントをしないということに注意してください。 それは呼び出し側の責任です。 これらの関数が NULL を返した場合、 呼び出し側はメモリリークを防ぐために、val
の参照カウントの デクリメントを行う必要が一般にはあるでしょう。
AV や HV に未定義値を保管しなければならないこともあります。 これは珍しい場合ですが、手の込んだものになります。 なぜなら、未定義の SV が必要なら、&PL_sv_undef
を使うことになるからです。
例えば、直感ではこの XS コードは:
AV *av = newAV();
av_store( av, 0, &PL_sv_undef );
以下の Perl コードと等価です:
my @av;
$av[0] = undef;
残念ながら、これは正しくありません。 AV は、配列要素がまだ初期化されていないことを示すための印として &PL_sv_undef
を使います。 従って、上述の Perl コードは exists $av[0]
は真ですが、 XS コードによって生成された配列では偽です。
HV に &PL_sv_undef
を保管する時にも別の問題が起こりえます:
hv_store( hv, "key", 3, &PL_sv_undef, 0 );
実際これは undef
値を作りますが、key
の値を変更しようとすると、 以下のようなエラーが出ます:
Modification of non-creatable hash value attempted
perl 5.8.0 では、&PL_sv_undef
は制限ハッシュのプレースホルダを マークするためにも使われていました。 これは、ハッシュを反復するときや hv_exists
関数でキーを チェックするときには、そのようなハッシュエントリは現れないということです。
&PL_sv_true
や &PL_sv_false
を AV や HV に保管するときにも同じような 問題が起こります。 このような要素を修正しようとすると、以下のようなエラーが出ます:
Modification of a read-only value attempted
長い物語を短くすると、特殊変数 &PL_sv_undef
, &PL_sv_true
, &PL_sv_false
を AV や HV に使えますが、何をしているかを知っている必要が あります。
一般的に、AV や HV に未定義値を保管したいなら、&PL_sv_undef
を使わず、 newSV
関数を使って新しい未定義値を使ってください; 例えば:
av_store( av, 42, newSV(0) );
hv_store( hv, "foo", 3, newSV(0), 0 );
リファレンスは、(リファレンスを含む) 他のスカラ型を指す特別なスカラ型です。
リファレンスを生成するには、
SV* newRV_inc((SV*) thing);
SV* newRV_noinc((SV*) thing);
thing
には、SV*
, AV*
, HV*
のいずれかを置くことができます。 これら二つの関数は、newRV_inc
が thing
の参照カウントを インクリメントするが newRV_noinc
はインクリメントしないという点を 除き、同一です。 歴史的な理由により、newRV
は newRV_inc
の同義語となっています。
リファレンスができれば、以下のマクロを使ってリファレンスの参照外し (dereference)ができます。
SvRV(SV*)
というマクロが使うことができ、返された SV*
を AV*
か HV*
に キャストして、適切なルーチンを呼ぶことになります。
SV がリファレンスであるかどうかを確認するために、以下のマクロを 使うことができます。
SvROK(SV*)
リファレンスが参照している型を見つけるために、以下のマクロを使いその戻り値を チェックします。
SvTYPE(SvRV(SV*))
戻り値として返される型で有益なものは以下の通りです。
SVt_IV スカラ
SVt_NV スカラ
SVt_PV スカラ
SVt_RV スカラ
SVt_PVAV 配列
SVt_PVHV ハッシュ
SVt_PVCV コード
SVt_PVGV グロブ (ファイルハンドルかも)
SVt_PVMG bress されたかマジカルなスカラ
詳しくはヘッダファイル sv.h を参照してください。
リファレンスはオブジェクト指向プログラミングをサポートするためにも 使われます。 perl のオブジェクト指向用語では、オブジェクトとはパッケージ (もしくはクラス)に bless された単純なリファレンスです。 一度 bless されれば、プログラマーはそのリファレンスをクラスにおける様々な メソッドにアクセスするために使うことができます。
以下の関数を使って、リファレンスをパッケージに bless することができます。
SV* sv_bless(SV* sv, HV* stash);
引数 sv
はリファレンス値でなければなりません。 引数 stash
はリファレンスが属するクラスを指定します。 クラス名のstashへの変換についての詳細は "Stashes and Globs" を 参照してください。
/* Still under construction */
まだ存在していなければ、rv をリファレンスにアップグレードします。 rv が指し示すための新たな SV を生成します。 classname
がヌルでなければ、SV は指定されたクラスに bless され、 SV が返されます。
SV* newSVrv(SV* rv, const char* classname);
整数、符号なし整数、倍精度実数を rv
が参照している SV へコピーします。 SV は classname
がヌルでなければ bless されます。
SV* sv_setref_iv(SV* rv, const char* classname, IV iv);
SV* sv_setref_uv(SV* rv, const char* classname, UV uv);
SV* sv_setref_nv(SV* rv, const char* classname, NV iv);
ポインタ値(アドレスであって、文字列ではありません!)を rv が 参照している SV へコピーします。 SV は classname
がヌルでなければ bless されます。
SV* sv_setref_pv(SV* rv, const char* classname, PV iv);
文字列を rv
が参照している SV へコピーします。 length に 0 を設定すると、Perl が文字列の長さを計算します。 SV は classname
がヌルでなければ bless されます。
SV* sv_setref_pvn(SV* rv, const char* classname, PV iv, STRLEN length);
SV が特定のクラスに bless されているかどうかを検査します。 これは継承の関係のチェックはしません。
int sv_isa(SV* sv, const char* name);
SV が bless されたオブジェクトのリファレンスであるかどうかを検査します。
int sv_isobject(SV* sv);
SV が特定のクラスから派生したものがどうかを検査します。 SV は bless されたオブジェクトのリファレンスでも、 クラス名を保持している文字列であってもかまいません。 これは UNIVERSAL::isa
の機能を実装している関数です。
bool sv_derived_from(SV* sv, const char* name);
ある特定のクラスの派生オブジェクトを受け取ったかどうか検査するには、 以下のように書く必要があります。
if (sv_isobject(sv) && sv_derived_from(sv, class)) { ... }
undef という値を持つあなたの Perl スクリプトからアクセスできる新たな Perl の変数を生成するには、以下に示すルーチンを変数の型に応じて 使います。
SV* get_sv("package::varname", TRUE);
AV* get_av("package::varname", TRUE);
HV* get_hv("package::varname", TRUE);
二番目のパラメータとして TRUE を使っているということに注意してください。 新しい変数はここでデータ型に対する適切なルーチンを使うことで 設定することができます。
TRUE
引数とビット和を取って、幾つかの追加機能を有効とするような 二つのマクロがあります。
変数に多重定義 (multiply defined) であると印を付け:
Name <varname> used only once: possible typo
警告を防ぎます。
以下の警告を:
Had to create <varname> unexpectedly
変数が、その関数の呼び出し以前に存在してなかった場合に発生させます。
パッケージ名を指定しなかった場合、変数はカレントパッケージで 生成されます。
Perl は参照カウント駆動(reference count-driven)のガベージコレクション 機構を使用しています。 SV、AV、そしてHV(以下 xV と省略します) はその一生を参照カウント 1 から始めます。 xV の参照カウントが0まで落ちた場合、そのリファレンスは破棄されて、 それが使っていたメモリは 再利用できるようにされます。
これは、Perl レベルにおいては、変数が undef されるとかリファレンスを 保持している最後の変数が変更されたとか上書きされるということがない限りは 起こりません。 しかし内部的には、参照カウントは以下に挙げるマクロを使って 操作することができます。
int SvREFCNT(SV* sv);
SV* SvREFCNT_inc(SV* sv);
void SvREFCNT_dec(SV* sv);
その引数の参照カウントを操作する別の関数が一つあります。 newRV_inc
という関数がそれです。 これは指定された引数の参照を生成して、その副作用として引数の 参照カウントをインクリメントします。 もしこの副作用が邪魔であれば、newRV_noinc
を代わりに使ってください。
たとえば、XSUB 関数からリファレンスを返したいと思ったとしましょう。 XSUB ルーチンの中で、初期値として参照カウント 1 を持つ SV を生成します。 それから今作成した SV を引数にして newRV_inc
を呼びます。 これは新たな SV としての参照を返しますが、newRV_inc
に引数として渡した SV の参照カウントは 2 にインクリメントされます。 ここで XSUB ルーチンからそのリファレンスを戻り値として返し、SV のことは 忘れましょう。 けれども Perl は忘れてません! 戻り値で返されたリファレンスが破棄されたときにはいつも、元々の SV の 参照カウントが 1 へと減じられ、そして何事もおこりません。 その SV は、Perl 自身が終了するまではそれにアクセスするなんの手段も 持たずに中ぶらりんになります。
ここでの正しい手順は、newRV_inc
ではなく newRV_noinc
を 使うということです。 これによって、最後のリファレンスが破棄されたときに SV のリファレンスカウントは0となってその SV が破棄されて、メモリ リークを食い止めます。
xV を破棄するのを助けるような便利な関数が幾つかあります。 これらの関数は「揮発性」(mortality) のコンセプトを導入します。 ある揮発性の xV はその参照カウントをデクリメントするようにマークしますが、 実際には「ちょっと後」(a short time later)までデクリメントが 行なわれません。 一般的には、「ちょっと後」とは、XSUB 関数の呼び出しのような Perl の一つの文です。 揮発性の xV が持っている参照カウントの デクリメントを行うタイミングの決定は二つのマクロ、SAVETMPS と FREETMPS に依存しています。 これら二つのマクロについての説明は perlcall と perlxs を参照してください。
「揮発化」("Mortalization") はそれから、SvREFCNT_dec
に決定権を委ねます。 しかし、ある変数を二度揮発的にした場合、その参照カウントは後で 二度デクリメントされます。
「揮発性」SV は主に、perl のスタックに置かれる SV に対して使われます。 例えば、単に数値を呼び出したサブルーチンに渡すために作られた SV は スタックからポップされたときに自動的に片付けられるように揮発性になります。 同様に、(スタックにプッシュされた) XSUB から返された結果はしばしば 揮発性となります。
揮発性の変数を生成するには、以下の関数を使います:
SV* sv_newmortal()
SV* sv_2mortal(SV*)
SV* sv_mortalcopy(SV*)
最初のものは(値のない)揮発性の SV を生成し、ふたつめは既にある SV を 揮発性の SV に変換します(そして、このために SvREFCNT_dec
を呼び出しを 遅らせます)。 三つめは、既に存在する SV の揮発性のコピーを生成します。 sv_newmortal
は値のない新しい SV を作るので、普通は sv_setpv
, sv_setiv
などを使って作らなければなりません:
SV *tmp = sv_newmortal();
sv_setiv(tmp, an_integer);
これは C の複数文なので、代わりにこの慣用法がとても一般的です:
SV *tmp = sv_2mortal(newSViv(an_integer));
揮発性の変数を生成するに当たっては十分注意すべきです。 もし、同じ変数を複合コンテキストの中で揮発性にしたり、ある変数を複数回 揮発性にしてしまったりすればおかしな自体が起こるかもしれません。 保留した SvREFCNT_dec
として「揮発化」を考えるとこのような問題を 最小化する助けになるでしょう。 例えば、スタック上で使っても生き残るのに十分に大きな REFCNT を持つと 知っている SV を渡す場合、揮発化は不要です。 SvREFCNT_inc
と sv_2mortal
をするかどうかはっきりしないときは、 sv_mortalcopy
を作るのがより安全です。
揮発性のルーチンは、単に SV のためだけではありません -- AV や HV も、sv_2mortal
や sv_mortalcopy
ルーチンに、アドレスを (SV*
にキャストして) 渡すことで、揮発性にすることができます。
スタッシュ ("stash")とは、パッケージ内で定義された全ての変数が 入っているハッシュのことです。 ハッシュテーブルにあるそれぞれの key は、(同じ名前のすべての異なる型の オブジェクトで共有される) シンボル名で、ハッシュテーブルの個々の 値は、(グローバル値のための) GV と呼ばれます。 GV には、以下のものを含む (これらに限りませんが)、その名前の様々な オブジェクトへのリファレンスが次々に入ることになります。
Scalar Value
Array Value
Hash Value
I/O Handle
Format
Subroutine
main
パッケージにあるアイテムを保持する PL_defstash
と呼ばれる スタッシュがあります。 他のパッケージにあるアイテムを取得するため には、パッケージ名に「::」を付加します。 Foo
というパッケージにあるアイテムは Foo::
という PL_defstash の中にあります。 パッケージ Bar::Baz
にあるアイテムは Bar::
のスタッシュの中の Baz::
のスタッシュの中にあります。
特定のパッケージの HV ポインタの入手には、以下の関数が使えます:
HV* gv_stashpv(const char* name, I32 flags)
HV* gv_stashsv(SV*, I32 flags)
最初の関数が、リテラル文字列をとり、二番目が SV に入れた文字列を使います。 stash は単なるハッシュなので、HV*
を受け取るということを 忘れないでください。 flags
フラグが GV_ADD にセットされている場合には新たなパッケージを 生成します。
gv_stash*v
が要求する name はシンボルテーブルを手に入れようとする パッケージの名前です。 デフォルトのパッケージは、main
というものです。 多重にネストしたパッケージであれば、Perl での場合と同様に、 ::
で区切って gv_stash*v
に名前を渡すのが正しい方法です。
あるいは、もし bless されたリファレンスである SV があれば、 以下のようにしてを使ってもスタッシュポインタを探すことができ:
HV* SvSTASH(SvRV(SV*));
パッケージ名自身は、以下のようにして得られます:
char* HvNAME(HV* stash);
Perl スクリプトへ bless された値を返す必要があれば、以下の関数が使えます:
SV* sv_bless(SV*, HV* stash)
最初の引数 SV*
はリファレンスで、二番目の引数がスタッシュです。 返された SV*
は、他の SV と同様に使うことができます。
リファレンスと bless についてのより詳しい情報は perlref を 参照してください。
スカラ変数は通常、整数、倍精度、ポインタ、リファレンスのうちの いずれか一つの型をとります。 Perl は実際のデータに対して、蓄積されている型から要求されている型へ、 自動的に変換を行ないます。
ある種のスカラ変数は、複数の型のスカラデータを持つようになっています。 たとえば変数 $!
は、errno
の数値としての値と、 strerror
や sys_errlist[]
から得たのと同値な文字列を持っています。
SV に複数のデータ値を入れるようにするには、二つのことを しなくてはなりません。 スカラ型を別に追加するために sv_set*v
ルーチンを使用すること。 それから、フラグを設定して Perl に複数のデータを 持っていることを知らせることです。 フラグを設定するための四つのマクロは以下のものです:
SvIOK_on
SvNOK_on
SvPOK_on
SvROK_on
使用するマクロは、最初にどの sv_set*v
ルーチンを呼ぶのかに 関わってきます。 これは、sv_set*v
ルーチンはすべて特定のデータ型のビットだけを 設定して、他をクリアしてしまうからです。
たとえば、"dberror" という新しい Perl 変数を作って、エラー値を数値と メッセージ文字列で持つようにするには、以下のように書きます:
extern int dberror;
extern char *dberror_list;
SV* sv = get_sv("dberror", TRUE);
sv_setiv(sv, (IV) dberror);
sv_setpv(sv, dberror_list[dberror]);
SvIOK_on(sv);
sv_setiv
と sv_setpv
の順序が逆であった場合、SvIOK_on
マクロの 代わりに SvPOK_on
マクロを呼ばなければなりません。
[この節はまだ作成中です。 ここにある全ては無視してください。 張り紙禁止。 許可されていないこと全ては禁止。]
すべての SV は magical、つまり、通常の SV が持っていないような特殊な 属性を持つようにすることができます。 これらの属性は MAGIC
として typedef されている struct magic
の リンクリストにある SV 構造体に格納されます。
struct magic {
MAGIC* mg_moremagic;
MGVTBL* mg_virtual;
U16 mg_private;
char mg_type;
U8 mg_flags;
I32 mg_len;
SV* mg_obj;
char* mg_ptr;
};
これは、パッチレベル 0 の時点でのものです。 変更される可能性があります。
Perl は sv_magic 関数を使った SV にマジックを追加します。
void sv_magic(SV* sv, SV* obj, int how, const char* name, I32 namlen);
引数 sv
は、新たにマジック機能を獲得する SV へのポインタです。
sv
がまだマジカルでなければ、Perl は sv
を SVt_PVMG
に変換 するために SvUPGRADE
を使います。 Perl はそれから、マジック機能のリンクリストの先頭にそれを追加します。 以前に存在していた同じタイプのマジックは削除されます。 これはオーバーライドすることができ、 複数の同じ型のマジックのインスタンスを一つの SV に 結び付けることができるということに注意してください。
引数 name
と namlen
はある文字列と magic とを結び付けるために 使われます。 典型的には変数の名前です。 namlen
は mg_len
フィールドに格納され、name
がヌルなら、 namlen
が 0 より大きいか、0 かに依存して、それぞれ name
の savepvn
コピーか、name
自身に保管されます。 特殊な場合として、(name && namlen == HEf_SVKEY)
なら name
は SV*
を含んでいるものと仮定して REFCNT をインクリメントして そのままの形で保管されます。
関数 sv_magic は how
を、あらかじめ定義されている マジック仮想テーブル("Magic Virtual Table") のどれを mg_virtual
フィールドに設定するかを決定するのに使います。 後述する "Magic Virtual Tables" の節を参照してください。 how
引数もまた mg_type
フィールドに保管されます。 how
の値は perl.h にある PERL_MAGIC_foo
マクロの集合から 選ばれるべきです。 これらのマクロが追加される前は、Perl の内部では文字リテラルを直接 使っていたので、古いコードや文書では例えば PERL_MAGIC_uvar
の 代わりに 'U' マジックを使っているものに出会うことがあるかもしれません。
引数 obj
は MAGIC
構造体の mg_obj
フィールドに格納されます。 これが sv
引数と同じでなかった場合、obj
の参照カウントは インクリメントされます。 同じであった場合、もしくは引数 how
が PERL_MAGIC_arylen
かヌルポインタであった場合には、obj
は 参照カウントのインクリメントをさせることなく格納されます。
SV にマジックを追加する、より柔軟な方法については perlapi の sv_magicext
も参照してください。
同様に HV
にマジックを付加する関数があります。
void hv_magic(HV *hv, GV *gv, int how);
これは単純に sv_magic
を呼び出し、引数 gv
を強制的に SV
にします。
SV からマジックを取り除くには、sv_unmagic という関数を呼び出します。
void sv_unmagic(SV *sv, int type);
引数 type
は、SV
が magical にされたときの how
の値と同じに なるようにすべきです。
MAGIC
構造体の mg_virtual
フィールドは MGVTBL
へのポインタで、 これは関数ポインタの構造体であり、また対応する変数に対して 適用される可能性のあるさまざまな操作を扱うための 「マジック仮想テーブル」("Magic Virtual Table") を意味しています。
MGVTBL
は、以下に挙げる 5 種類(あるいは時々 8 種類)の ポインタを持っています。
int (*svt_get)(SV* sv, MAGIC* mg);
int (*svt_set)(SV* sv, MAGIC* mg);
U32 (*svt_len)(SV* sv, MAGIC* mg);
int (*svt_clear)(SV* sv, MAGIC* mg);
int (*svt_free)(SV* sv, MAGIC* mg);
int (*svt_copy)(SV *sv, MAGIC* mg, SV *nsv, const char *name, int namlen);
int (*svt_dup)(MAGIC *mg, CLONE_PARAMS *param);
int (*svt_local)(SV *nsv, MAGIC *mg);
この MGVTBL は perl.h の中でコンパイル時に設定され、現在 19 の型 (オーバーロード込みで 21)があります。 これらの異なった構造体は、関数が呼び出されたときに依存して 追加動作を行うような様々なルーチンへのポインタを保持しています。
関数ポインタ その振る舞い
---------------- ------------
svt_get SV の値が取得された前に何かを行う。
svt_set SV に値を代入した後で何かを行う。
svt_len SV の長さを報告する。
svt_clear SV が表わしているものををクリアする。
svt_free SV に結び付けられてい領域を解放する。
svt_copy tie された変数のマジックを tie された要素にコピーする
svt_dup スレッドのクローン化中にマジック構造体を複製する
svt_local 'local' 中にマジックをローカル変数にコピーする
たとえば、vtbl_sv
(PERL_MAGIC_sv
の mg_type
に対応します)と 呼ばれる MGVTBL 構造体の内容は以下の様になっています。
{ magic_get, magic_set, magic_len, 0, 0 }
したがって、ある SV がマジカルであると決定されてその型が PERL_MAGIC_sv
であったとき、操作が実行されたならば、magic_get
が 呼び出されます。 マジカル型に対するルーチンはすべて、magic_
で始まります。 NOTE: マジックルーチンは Perl API の一部として扱われず、 Perl ライブラリによってエクスポートされません。
末尾の三つのスロットは最近追加されたもので、ソースコードの互換性のために、 mg_flags に MGf_COPY, MGf_DUP, MGf_LOCAL のいずれか一つが設定されている 場合にのみチェックされます。 これは、ほとんどのコードは vtable を 5 要素の値として定義したままで よいということです。 これらの三つは現在のところスレッドのコードのみで使われていて、 変更される可能性が高いです。
現時点でのMagic Virtual Tables の種類は以下の通りです。
mg_type
(old-style char and macro) MGVTBL Type of magic
-------------------------- ------ -------------
\0 PERL_MAGIC_sv vtbl_sv 特殊スカラ変数
A PERL_MAGIC_overload vtbl_amagic %OVERLOAD ハッシュ
a PERL_MAGIC_overload_elem vtbl_amagicelem %OVERLOAD ハッシュ要素
c PERL_MAGIC_overload_table (none) スタッシュのオーバーロード
テーブル(AMT) を保持
B PERL_MAGIC_bm vtbl_bm Boyer-Moore (高速文字列検索)
D PERL_MAGIC_regdata vtbl_regdata 正規表現マッチング位置データ
(@+ と @- の変数)
d PERL_MAGIC_regdatum vtbl_regdatum 正規表現マッチング位置データ
要素
E PERL_MAGIC_env vtbl_env %ENV ハッシュ
e PERL_MAGIC_envelem vtbl_envelem %ENV ハッシュ要素
f PERL_MAGIC_fm vtbl_fm フォーム行(「コンパイル済み」
フォーマット)
g PERL_MAGIC_regex_global vtbl_mglob m//g のターゲット / study() した文字列
H PERL_MAGIC_hints vtbl_sig %^H ハッシュ
h PERL_MAGIC_hintselem vtbl_hintselem %^H ハッシュ要素
I PERL_MAGIC_isa vtbl_isa @ISA 配列
i PERL_MAGIC_isaelem vtbl_isaelem @ISA 配列要素
k PERL_MAGIC_nkeys vtbl_nkeys scalar(keys()) 左辺値
L PERL_MAGIC_dbfile (none) デバッガの %_<filename
l PERL_MAGIC_dbline vtbl_dbline デバッガの %_<filename 要素
o PERL_MAGIC_collxfrm vtbl_collxfrm ロケール照合変換
P PERL_MAGIC_tied vtbl_pack tie された配列やハッシュ
p PERL_MAGIC_tiedelem vtbl_packelem tie された配列やハッシュの要素
q PERL_MAGIC_tiedscalar vtbl_packelem tie されたスカラやハンドル
r PERL_MAGIC_qr vtbl_qr 事前コンパイルされた qr// 正規表現
S PERL_MAGIC_sig vtbl_sig %SIG ハッシュ
s PERL_MAGIC_sigelem vtbl_sigelem %SIG ハッシュ要素
t PERL_MAGIC_taint vtbl_taint 汚染性
U PERL_MAGIC_uvar vtbl_uvar エクステンションで使用可能
v PERL_MAGIC_vec vtbl_vec vec() 左辺値
V PERL_MAGIC_vstring (none) v-文字列スカラ
w PERL_MAGIC_utf8 vtbl_utf8 UTF-8 長さ+オフセットキャッシュ
x PERL_MAGIC_substr vtbl_substr substr() 左辺値
y PERL_MAGIC_defelem vtbl_defelem 影の "foreach" 反復子
変数 / スマート引数
自動有効化
# PERL_MAGIC_arylen vtbl_arylen 配列の長さ ($#ary)
. PERL_MAGIC_pos vtbl_pos pos() 左辺値
< PERL_MAGIC_backref vtbl_backref 弱いリファレンスへの後方ポインタ
~ PERL_MAGIC_ext (none) エクステンションで使用可能
: PERL_MAGIC_symtab (none) シンボルテーブルとして使われるハッシュ
% PERL_MAGIC_rhash (none) 制限ハッシュとして使われるハッシュ
@ PERL_MAGIC_arylen_p vtbl_arylen_p @a から $#a へのポインタ
テーブル中で大文字小文字の両方が存在していた場合、大文字は典型的には複合型 (リストもしくはハッシュ)の種類を表わすのに使われ、小文字はその複合型の 要素を表わすのに使われます。 内部コードにはこの大文字小文字の関係を使っているものもあります。 しかし、'v' と 'V' (ベクタと v-文字列) は全く関係がありません。
マジック型 PERL_MAGIC_ext
と PERL_MAGIC_uvar
は エクステンションから使われ、Perl 自身からは使われないように特別に 定義されています。 エクステンションは PERL_MAGIC_ext
マジックを、 プライベート情報を変数(典型的なオブジェクト)に「アタッチ」(attach) するために使うことができます。 これは、通常の perl コードが(ハッシュオブジェクトの要素を使うのとは違って) そのプライベート情報を壊す恐れがないのでとても便利です。
同様に、PERL_MAGIC_uvar
マジックは、スカラの値が使われたり 変更されたりしたときに C 関数を呼び出すという、tie() とよく似た形で 使えます。 MAGIC
の mg_ptr
フィールドは ufuncs
構造体へのポインタです:
struct ufuncs {
I32 (*uf_val)(pTHX_ IV, SV*);
I32 (*uf_set)(pTHX_ IV, SV*);
IV uf_index;
};
SV が読み書きされたとき、uf_index
を最初の引数、SV へのポインタを 2 番目の引数として uf_val
または uf_set
関数が呼び出されます。 どのように PERL_MAGIC_uvar
マジックを追加するかの簡単な例を以下に 示します。 ufuncs 構造体は sv_magic によってコピーされるので、スタック上に安全に 割り当てられることに注意してください。
void
Umagic(sv)
SV *sv;
PREINIT:
struct ufuncs uf;
CODE:
uf.uf_val = &my_get_fn;
uf.uf_set = &my_set_fn;
uf.uf_index = 0;
sv_magic(sv, 0, PERL_MAGIC_uvar, (char*)&uf, sizeof(uf));
PERL_MAGIC_uvar
を配列にアタッチすることは可能ですが、何の意味も ありません。
ハッシュについては、ハッシュのキー(値ではありません)の制御をするための 専門化されたフックがあります。 このフックは、ufuncs
構造体の "set" 関数が NULL のとき、 PERL_MAGIC_uvar
'get' マジックを呼び出します。 このフックは、hv_store_ent
, hv_fetch_ent
, hv_delete_ent
, hv_exists_ent
関数を通して SV
で指定されたキーでハッシュに アクセスされたときに有効になります。 ..._ent
接尾辞を持たない関数を等して文字列としてキーにアクセスすると、 フックを通りません。 詳細な説明については "Guts" in Hash::Util::Fieldhash を参照してください。
複数のエクステンションが PERL_MAGIC_ext
や PERL_MAGIC_uvar
マジックを 使う可能性があるので、エクステンションがそれを扱うには気をつけることが 重要であることに注意してください。 典型的には、これはオブジェクトをエクステンションが扱えるように同じクラスに bless するときにのみ使います。 PERL_MAGIC_ext
マジックでは、これはまた、プライベートなデータ領域の 先頭においてそれをチェックするために I32「シグネチャ」(signature) を 付加するのに適切なものです。
sv_set*()
と sv_cat*()
といった関数群はそのターゲットに対して 'set' マジックを 起動しない ということにも注意してください。 これには、ユーザーが svSETMAGIC
マクロを呼び出した後でこれらの関数を 呼び出すか、あるいは sv_set*_mg()
か sv_cat*_mg()
の何れかの関数を使わなければなりません。 同様に、一般的な C コードは、 それがマジックを扱っていないような関数から得られた SV を使っているのであれば、 'get' マジックを起動するために SvGETMAGIC
を呼び出さなければなりません。 これらの関数については perlapi を参照してください。 例えば、sv_cat*()
関数群の 呼び出しは通常引き続いて SvSETMAGIC()
を呼び出す必要がありますが、 SvGETMAGIC
が先行している必要はありません; なぜなら、その実装は 'get' マジックを扱うからです。
MAGIC* mg_find(SV*, int type); /* Finds the magic pointer of that type */
このルーチンは SV に格納されている MAGIC
構造体へのポインタを 返します。 SV がマジカル機能を持っていなければ、NULL
が返されます。 また、SV が Svt_PVMG の型でなければ Perl はコアダンプするかもしれません。
int mg_copy(SV* sv, SV* nsv, const char* key, STRLEN klen);
このルーチンは sv
が持っているマジックの型を検査します。 mg_type フィールドが大文字であれば、mg_obj が nsv
にコピーされますが、 mg_type フィールドは小文字に変更されます。
tie されたハッシュと配列は PERL_MAGIC_tied
マジック型の magical beast です。
警告: リリース 5.004 以降、配列やハッシュに対するアクセス 関数の正しい使い方は、幾つかの注意点を理解していることを要求しています。 これら幾つかの注意点は実際には API におけるバグとして みなされるものであって、将来のリリースにおいては修正されます。 また、注意点は [MAYCHANGE] というブラケットで囲まれています。 このセクションにある情報をあなたが実際に使おうというのであれば、 将来それらは警告なしに変わる可能性があることに注意してください。
perl の tie 関数は、ある変数と GET、SET 等といった様々なメソッドを 実装しているオブジェクトとを結び付けるものです。 XSUB から perl の tie 関数と等価な働きをさせるには、ちょっとした オマジナイをしなければなりません。 以下の例が必要なステップです - まず最初にハッシュを作り、それから tie メソッドを実装するクラスに bless した二番目のハッシュを作ります。 最後に二つのハッシュを tie し、新たに生成した tie されたハッシュに対する リファレンスを返します。 以下の例では MyTie クラスの中で TIEHASH を呼び出していないということに 注意してください。 この件に関する詳細は "Calling Perl Routines from within C Programs" を 参照してください。
SV*
mytie()
PREINIT:
HV *hash;
HV *stash;
SV *tie;
CODE:
hash = newHV();
tie = newRV_noinc((SV*)newHV());
stash = gv_stashpv("MyTie", GV_ADD);
sv_bless(tie, stash);
hv_magic(hash, (GV*)tie, PERL_MAGIC_tied);
RETVAL = newRV_noinc(hash);
OUTPUT:
RETVAL
tie された配列を引数に与えられたときの av_store
関数は、単に配列の magic を mg_copy
を使って「保管」されるように値をコピーするだけです。 この関数は、その値が実際には配列に格納する必要のないものであることを 示す NULL を返す可能性があります。 [MAYCHANGE] tie された配列に対して av_store
を呼び出した後、呼び出し側は TIEARRAY オブジェクトに対して Perl レベルの "STORE" メソッドを起動するために av_store
を呼び出すことが通常は必要となります。 av_store
が NULL を返したならば、メモリリークを防ぐために SvREFCNT_dec(val)
を呼び出すことが必要となります。 [/MAYCHANGE]
先のパラグラフの説明は、tie されたハッシュにアクセスするのに使用する hv_store
と hv_store_ent
についても同様です。
av_fetch
と、対応するハッシュ関数 hv_fetch
および hv_fetch_ent
は 実際には mg_copy
を使って初期化が行なわれている未定義の揮発値を返します。 返された値はすでに揮発性なので、解放する必要がないことに注意してください。 [MAYCHANGE] しかし、TIE オブジェクトに対応した perl レベルの "FETCH" メソッドを実行するには、返されたその値に対して mg_get()
を呼び出す必要があるでしょう。 同様に、TIE オブジェクトに対する "STORE" メソッドの起動である sv_setsv
を使って適切な値を代入した後で、返された値に対して mg_set()
を呼び出すことができます。 [/MAYCHANGE]
[MAYCHANGE] 言い換えれば、配列やハッシュをフェッチしたりストアする関数は、 tie されている配列やハッシュに対する場合には実際に値をフェッチしたり 保管したりするわけではないということです。 それらの関数は「保管」されたり「フェッチ」された値に対してマジックを 付加するために、単に mg_copy
を呼び出すだけです。
現在(バージョン 5.004)、ハッシュや配列に対するアクセス関数を使用する 際には、ユーザーが「通常の」ハッシュや配列なのか、あるいはそれが tie されたものであるのかを気をつけることが要求されています。 将来のバージョンでは、この API は tie されたデータに対するアクセスと 通常のデータに対するアクセスをより透過的にするために変更されるかも しれません。 [/MAYCHANGE]
TIEARRAY や TIEHASH といったインターフェースが、統一的な ハッシュ/配列構文を使うための perl メソッドを起動をするための単なる 砂糖であることを良く理解したことでしょう。 これらの砂糖の使用はいくらかのオーバーヘッド(通常、FETCH/STORE 操作 当たり二つから四つの余分なオペコード、それに加えてメソッドを 起動するために必要なすべての揮発性変数の生成)を招きます。 このオーバーヘッドは TIE メソッド自身がしっかりしたものであれば、ほぼ 同等なくらい小さなものでしかありませんが、ほんの少し文が長いだけでも オーバーヘッドは無視できないものになります。
Perl には非常に便利な構造があります。
{
local $var = 2;
...
}
この構造は以下のものと ほぼ 同じです
{
my $oldvar = $var;
$var = 2;
...
$var = $oldvar;
}
両者の最も大きな違いは、最初のものが goto
、return
、die
/eval
など どのようにブロックから脱出しようとも、 $var の元々の値を復帰するということです。 効率といった面では大きな違いはありません。
Perl API を通して C から同様の処理を行う方法もあります。 擬似ブロック(pseudo-block)を生成し、そのブロックの最後で自動的に 復帰するような幾つかの変更を行います。 ブロックから抜けるのは、明示的に抜けるための指示があっても良いし、 非局所的な脱出(die() を使ったもの)でもかまいません。 ブロックに似たこの構造は ENTER
/LEAVE
マクロのペアによって 生成されます("Returning a Scalar" in perlcall を参照してください)。 このような構造ではなにか重要なローカル化された タスクのための特別なものを作成したり、あるいは 既に存在しているもの(Perl のサブルーチン/ブロックに束縛されたものとか、 あるいは解放する一時変数のペア)を使うことも可能です (二番目のケースでは、ローカル化するためのオーバーヘッドはほとんど 無視できるものです)。 すべての XSUB は自動的に ENTER
/LEAVE
の ペアによって囲まれているということに注意してください。
このような 擬似ブロック の中では以下のサービスが利用可能です:
SAVEINT(int i)
SAVEIV(IV i)
SAVEI32(I32 i)
SAVELONG(long i)
これらのマクロはそれを囲む 擬似ブロック において 整数変数 i
の値をリストアするようにします。
SAVESPTR(s)
SAVEPPTR(p)
これらのマクロは、ポインタs
もしくは p
の値を リストアします。 s
は SV*
に対する型変換をできるポインタでなければなりません。 p
は char*
への型変換が可能であるべきものです。
SAVEFREESV(SV *sv)
擬似ブロック の終端において sv
の参照カウントは デクリメントされます。 これは、遅延した SvREFCNT_dec
を行うための機構という意味で sv_2motral
に似たものです。 しかし、sv_2mortal
は sv
の生存時間を次の文の始めまで延ばす一方、 SAVEFREESV
は囲まれているスコープの終わりまで延ばします。 これらの生存時間は大きく異なるかもしれません。
また、SAVEMORTALIZESV
を比較します。
SAVEMORTALIZESV(SV *sv)
SAVEFREESV
と同様ですが、参照カウントを減らすのではなく、現在のスコープの 終わりで sv
を揮発化します。 これは普通、現在有効なスコープが実行を終了する文まで sv
を 生存させ続けます。
SAVEFREEOP(OP *op)
OP *
は 擬似ブロック の終端において op_free() されます。
SAVEFREEPV(p)
p
によって指し示されているメモリの塊は 擬似ブロック の終端で Safefree() されます。
SAVECLEARSV(SV *sv)
擬似ブロック の終端において、 sv
に対応している カレントのスクラッチパッドにおけるスロットをクリアします。
SAVEDELETE(HV *hv, char *key, I32 length)
擬似ブロック の終端で hv
にあるキー key
は削除されます。 key
によって指し示されている文字列は Safefree() されます。 short-lived storageにある key を持っているものがあった場合には 以下のようにして対応する文字列が再割り当てされます。
SAVEDELETE(PL_defstash, savepv(tmpbuf), strlen(tmpbuf));
SAVEDESTRUCTOR(DESTRUCTORFUNC_NOCONTEXT_t f, void *p)
擬似ブロック の終端において関数 f
が呼び出されます。 この関数 f
は p
のみを引数に取ります。
SAVEDESTRUCTOR_X(DESTRUCTORFUNC_t f, void *p)
疑似ブロック の最後に、関数 f
が(もしあれば)暗黙のコンテキスト 引数と p
で呼び出されます。
SAVESTACK_POS()
擬似ブロック の終端において Perl の内部スタック(SP
)のカレント オフセットがリストアされます。
以下の API リストは、変更可能なデータを指し示すポインタ (C のポインタか、Perl 的な GV *
のいずれか) を必要とする関数群です。 前述の int
を引数に取るマクロに似て、 int *
を引数に取る関数があります。
SV* save_scalar(GV *gv)
Perl コード local $gv
と等価です。
AV* save_ary(GV *gv)
HV* save_hash(GV *gv)
save_scalar
に似ていますが、@gv
と %gv
の局所化を行います。
void save_item(SV *item)
SV
のカレントの値を複製し、カレントの ENTER
/LEAVE
擬似ブロック を抜けるときに SV
の保存した値を復帰します。 マジックを扱いません。 マジックを有効にしたい場合は save_scalar
を使ってください。
void save_list(SV **sarg, I32 maxsarg)
複数の引数を長さ maxarg
の SV*
の配列 sarg
として取る save_item
の複数の値を取るバリエーションです。
SV* save_svref(SV **sptr)
save_scalar
に似ていますが、SV *
の復帰を行います。
void save_aptr(AV **aptr)
void save_hptr(HV **hptr)
save_svref
に似ていますが、AV *
と HV *
のローカル化を行います。
Alias
モジュールは 呼び出し側のスコープ 中での基本型のローカル化を 実装します。 スコープを持った何かのローカル化に興味のある人は そこに何があるかも見ておいた方が良いでしょう。
XSUB の仕組みは、Perl プログラムが C のサブルーチンを アクセスするための単純な方法です。 XSUB には、Perl プログラムからの引数を入れるスタックと、Perl のデータ 構造を C の等価なものにマッピングする方法を用意しています。
スタック引数は ST(n)
というマクロを使ってアクセスできます。 これは、n
番目のスタック引数を返すものです。 引数 0 は、Perl のサブルーチン呼び出しで渡された最初の引数です。 これらの引数は SV*
で、SV*
が使われるところであればどこでも 使うことができます。
ほとんどの場合には、C ルーチンからの出力は RETVAL 指示子と OUTPUT 指示子を使って扱うことができます。 しかし、引数スタックのスペースがすべての返却値を扱うのに十分で なくなる場合があります。 例としては、引数をとらないでローカルなタイムゾーンと夏時間の省略形の 二つの返却値を返す、POSIX の tzname() の呼び出しがあります。
このような状況を扱うためには、PPCODE ディレクティブを使い、さらに スタックを以下のマクロを使って拡張します:
EXTEND(SP, num);
ここで SP
はスタックポインタで、num
はスタックを拡張すべき 要素の数です。
スタック上に場所を確保したら、PUSHs
マクロを使って値をスタックへ プッシュします。 プッシュされた値はしばしば「揮発性」である必要があります( "Reference Counts and Mortality" を参照してください):
PUSHs(sv_2mortal(newSViv(an_integer)))
PUSHs(sv_2mortal(newSVuv(an_unsigned_integer)))
PUSHs(sv_2mortal(newSVnv(a_double)))
PUSHs(sv_2mortal(newSVpv("Some String",0)))
これで、tzname
を呼ぶ Perl プログラムでは、二つの値は 以下のように代入できます。
($standard_abbrev, $summer_abbrev) = POSIX::tzname;
スタックに値を積む、別の (おそらくはより簡単な) 方法は、 以下のマクロを使うことです。
XPUSHs(SV*)
こちらのマクロは、必要ならば自動的にスタックを調整してくれます。 このため、EXTEND
をスタックを拡張するために呼ぶ必要はありません。
この文書の以前のバージョンでの推奨にも関わらず、マクロ (X)PUSH[iunp]
は 複数の結果を返す XSUB には向いて いません。 このためには、上述の (X)PUSHs
マクロにこだわるか、代わりに新しい m(X)PUSH[iunp]
マクロを使ってください; "Putting a C value on Perl stack" を参照してください。
より詳しい情報は、perlxs と perlxstut を参照してください。
C プログラムから Perl サブルーチンを呼び出すために使用することのできる ルーチンが 四つあります。 その四つは:
I32 call_sv(SV*, I32);
I32 call_pv(const char*, I32);
I32 call_method(const char*, I32);
I32 call_argv(const char*, I32, register char**);
最もよく使われるはずのものは、call_sv
です。 引数 SV*
には呼び出される Perl サブルーチンの名前か、その サブルーチンへのリファレンスが含まれます。 二番目の引数には、そのサブルーチンが呼び出されたコンテキストを制御する フラグが置かれます。 これはサブルーチンに引数が渡されたか渡されていないか、エラーを どのようにトラップすべきなのか、どのように戻り値を返すのかを 制御するものです。
四つのルーチンはいずれも、サブルーチンが Perl スタック上に返した 引数の数を返します。
これらのルーチンは Perl v5.6.0 以前では perl_call_sv
などと 呼ばれていましたが、しかしこれらの名前は現在では非推奨です; 同じ名前の マクロが互換性のために提供されています。
これらのルーチンを使うときには(call_argv
を除いて)、プログラマが Perl スタックを操作しなくてはなりません。 以下のマクロと関数が用意されています:
dSP
SP
PUSHMARK()
PUTBACK
SPAGAIN
ENTER
SAVETMPS
FREETMPS
LEAVE
XPUSH*()
POP*()
C から Perl を呼び出す約束ごとについての詳しい記述は perlcall を参照してください。
Perl API 関数と共に使うような全てのメモリはこのセクションで 説明されているマクロを使って扱うべきです。 マクロは実際の malloc の 実装と、perl で使われているものとの差を透過的にします。
Perl と一緒に配布されていて、あなたがこれを使うことを推奨されている malloc の変種です。 これは様々な大きさの未割り付けのメモリをプールしておき、 より早く割り付け要求に応えようとするものです。 しかしながら一部のプラットフォームでは、これは不法なmallocエラーや freeエラーを引き起こす可能性があります。
これら三つのマクロはメモリの割り付けのために使われます:
Newx(pointer, number, type);
Newxc(pointer, number, type, cast);
Newxz(pointer, number, type);
1 番目の引数 pointer
は、新たにメモリを割り付けられる変数の 名前にします。
3 番目と 4 番目の引数 number
と type
は、指定された構造体を どれだけ割り付けるのかを指定します。 引数 type
は sizeof
に渡されます。 Newxc
に対する最後の引数 cast
は、引数 pointer
が 引数 type
と異なるときに使うべきものです。
Newx
や Newxc
とは異なり、Newxz
は割り付けたメモリのすべてを ゼロで埋めるために memzero
を呼び出します。
Renew(pointer, number, type);
Renewc(pointer, number, type, cast);
Safefree(pointer)
上記の三つのマクロは、メモリのバッファーサイズを変更したりもう 使わなくなったメモリ領域を解放するために使われます。 Renew
とRenewc
の引数は、“魔法のクッキー”引数が必要ないと いうことを除きそれぞれ New
と Newc
に一致します。
Move(source, dest, number, type);
Copy(source, dest, number, type);
Zero(dest, number, type);
この三つのマクロは、それぞれ割り付けたメモリ領域に対する移動、 複写、ゼロで埋めるといったことに使われます。 source
と dest
という引数は、転送元と転送先の開始番地への ポインタです。 Perl は、構造体 type
の大きさ (sizeof
関数を使います)のインスタンスの number
個分だけ、移動、複写、ゼロ埋めを行います。
最新リリースの Perl の開発では、Perl の「通常の」標準入出力ライブラリに 依存している部分を取り除くことと、Perl で別の標準入出力の実装が 使えるようにすることが試みられました。 これにより必然的に、Perl と共にコンパイルされた標準入出力の実装を 呼び出すような新しい抽象層が作られました。 すべての XSUB は、今では PerlIO 抽象層の関数を使うべきで、 これまで使っていた標準入出力に関してのすべての仮定はすべきではありません。
PerlIO 抽象化に関する詳しい記述は perlapio を参照してください。
たくさんのオペコード(これは内部的な perl スタックマシンでの基本的な 操作です)が SV をスタックに置きます。 しかしながら、SV に対する最適化のようなものは(通常は)毎回 行なわれるわけではありません。 オペコードは解放されたり、生成されることのない特別に割り当てられた SV (target) を再利用します。
それぞれの targets は、一度だけ生成して(ただし、後述する "Scratchpads and recursion" を参照のこと)、オペコードがスタックに 整数値、倍精度実数値、文字列といったものを置くことを必要とするときに、 スタックに target を置きます。
この target をスタックに置くためのマクロが PUSHTARG
です。 このマクロは、他の多くのマクロが (X)PUSH[iunp]
を通じて間接的に 使っているのと同様に、幾つかのオペコードで直接使われています。
ターゲットは再利用されるので、スタックに複数の値をプッシュするときには 注意しなければなりません。 以下のコードはあなたが考えているようには動作しません:
XPUSHi(10);
XPUSHi(20);
これは、「TARG
に 10 を設定して、TARG
へのポインタをスタックに プッシュする; TARG
に 20 を設定して、TARG
へのポインタをスタックに プッシュする」と解釈されます。 操作の終了時、スタックには値 10 と 20 はなく、値 を 20 に設定された TARG
へのポインタが二つあります。
複数の異なった値をプッシュしたい場合、(X)PUSHs
マクロを使うか、新しい m(X)PUSH[iunp]
マクロを使う必要があります; どちらもTARG
は使いません。 (X)PUSHs
マクロは単に SV* をスタックにプッシュし、この値は、 "XSUBs and the Argument Stack" で注意されているように、 しばしば「揮発性」である必要があります。 新しい m(X)PUSH[iunp]
マクロは、新しい揮発性値を ((X)PUSHmortal
を使って)作成し、それをスタックにプッシュし (mXPUSH[iunp]
マクロの場合もし必要なら拡張して)、それから値を設定します。 従って、前述の例を「修正」するのに以下のように書く代わりに:
XPUSHs(sv_2mortal(newSViv(10)))
XPUSHs(sv_2mortal(newSViv(20)))
単純にこう書けます:
mXPUSHi(10)
mXPUSHi(20)
関連する注意として、(X)PUSH[iunp]
を使うなら、*PUSH*
マクロが ローカル変数 TARG
を使うように、変数宣言に dTARG
が必要でしょう。 dTARGET
と dXSTARG
も参照してください。
残っている疑問は、オペコードに対する targets である SV をいつ 生成するのかということでしょう。 その答えは、カレントユニット -- サブルーチンもしくは(サブルーチンの 外側にある文のためのオペコードのための)ファイル -- が コンパイルされたときです。 この間、特別な無名配列が生成されます。 これはカレントユニットのためのスクラッチパッド (scrachpad) と 呼ばれるものです。
スクラッチパッドはカレントユニットのためのレキシカルやオペコードの ための target である SV を保持します。 SV があるスクラッチパッドを、 SV のフラグを見ることによって推測することができます。 レキシカルでは SVs_PADMY
されていて、targets では SVs_PADTMP
が セットされています。
オペコードと targets の間の対応は一対一ではありません。 あるユニットの翻訳木 (compile tree)にある異なるオペコードは、 これが一時変数の expected life と衝突していなければ同じ target を使うことが できます。
コンパイルされたユニットがスクラッチパッド AV へのポインタを 保持しているということは、100% 本当のことではありません。 実際は、(初期値では)一要素の AV へのポインタを保持していて、この要素が スクラッチパッド AV なのです。 なぜ、こういう余計な間接レベルを必要としているのでしょう?
その答えは 再帰 と、おそらく スレッド です。 これら二つは同じサブルーチンに対する別々の実行ポインタを 生成しようとするかもしれません。 子サブルーチンが(呼び出す子サブルーチンを覆っている寿命を持つ) 親サブルーチンの一時変数を上書きしてしまわないように、 親と子では、異なるスクラッチパッドを持つようにすべきです (かつ、レキシカルは分けておくべきなのです!)。
各サブルーチンは、スクラッチパッドの(長さが 1 の)配列を伴って生成されます。 サブルーチンに対する各エントリーはその時点での再帰の深さが この配列の長さよりも大きくないことをチェックします。 そして、もしそうであれば、新たなスクラッチパッドが生成されて配列へと プッシュされます。
このスクラッチパッドにある targets は undef
ですが、これらはすでに 正しいフラグによってマークされています。
ここで、Perl によって変換されたプログラムの内部形式を説明しましょう。 簡単な例から始めます。
$a = $b + $c;
これは次のような木構造へ変換されます(実際にはもっと複雑です)。
assign-to
/ \
+ $a
/ \
$b $c
この木構造は、Perl があなたのプログラムを解析したやり方を 反映していますが、実行の順序については反映していません。 ノードの実行順序を表わす木構造のノードを辿ろうとする別の 「スレッド」(thread) があります。 先の簡単な例では、次のようになります。
$b ---> $c ---> + ---> $a ---> assign-to
しかし、$a = $b + $c
に対する実際の解析木はこれと異なります。 一部のノードが最適化されています。 その結果として、実際の木構造が私たちの単純な例よりも多くのノードを 持っていたとしても、その実行順序は同じになります。
perl をデバッグ用にコンパイルした(通常は Configure
のコマンドラインで -DDEBUGGING
を使って行います)場合、Perl のコマンドラインで -Dx
を指定することによって解析木を検査することができます。 その出力はノード毎に数行を取り、$b+$c
は以下のようになります。
5 TYPE = add ===> 6
TARG = 1
FLAGS = (SCALAR,KIDS)
{
TYPE = null ===> (4)
(was rv2sv)
FLAGS = (SCALAR,KIDS)
{
3 TYPE = gvsv ===> 4
FLAGS = (SCALAR)
GV = main::b
}
}
{
TYPE = null ===> (5)
(was rv2sv)
FLAGS = (SCALAR,KIDS)
{
4 TYPE = gvsv ===> 5
FLAGS = (SCALAR)
GV = main::c
}
}
この木には五つのノード(TYPE
毎にひとつ)があって、そのうちの 三つだけが最適化されないものです(左側に数字のあるもの)。 与えられたノードのすぐ下にある子供は同じレベルのインデントにある {}
の ペアに対応します。 したがって、このリストは以下の木に対応します。
add
/ \
null null
| |
gvsv gvsv
実行順序は ===>
マークによって表わされますから、3 4 5 6
(ノード 6
は、上にあるリストには含まれません)となります。 つまり、gvsv gvsv add whatever
ということになります。
ノードのそれぞれは op を示し、これは Perl コア内部の基本的な操作です。 それぞれの操作を実装しているコードは pp*.c ファイルにあります; gvsv
型の op を実装している関数は pp_gvsv
、といった形です。 上述の木において、異なった op は異なった数の子を持ちます: add
は 二項演算子で、推測される通り、二つの子を持ちます。 様々に異なる数の子に対応するために、op データ構造には様々な種類があり、 異なった方法で互いにリンクしています。
op 構造体の最も単純な型は OP
です: これは子はありません。 単項演算子である UNOP
は一つの子を持ち、これは op_first
フィールドによって示されています。 二項演算子 (BINOP
) は op_first
フィールドだけでなく op_last
フィールドも持ちます。 最も複雑な op の型は LISTOP
で、任意の数の子を持ちます。 この場合、最初の子は op_first
で示され、最後の子は op_last
で 示されます。 その間の子は、最初の子から最後の子まで op_sibling
ポインタを反復的に 辿ることで見つけられます。
あと二つの op 型があります: PMOP
は正規表現を保持し、子はありません; また LOOP
は子があるかもしれませんしないかもしれません。 op_children
フィールドが非ゼロなら、LISTOP
のように振る舞います。 問題を複雑にするために、もし UNOP
が最適化の後実際には null
op になった場合 ("Compile pass 2: context propagation" を 参照してください)、これは以前の形に一致する形で子を持ちます。
木を調べるその他の方法は、B::Concise のようなコンパイラバックエンド モジュールを使うことです。
この木構造は、yacc が perl プログラムを読み込んでその構造を解析している 間にコンパイラによって生成されます。 yacc はボトムアップで動作するので、perl によるコンパイルの最初のパスで 行なわれます。
perl 開発者にとって興味深いのは、このパスで行なわれるいくつかの 最適化でしょう。 これは、"check routines" とも呼ばれる最適化です。 ノード名と対応するチェックルーチンとの間の対応は opcode.pl に 記述されています(このファイルを修正した場合には、make regen_headers
を 実行することを忘れないでください)。
チェックルーチンは、ノードが実行順序スレッドを除いて完全に 構築されたときに呼び出されます。 この時点では、構築されたノードに対する back-line が存在しないので、 トップレベルノードに対して、新たなノードを生成したりノードを 解放したりすることを含めて、ほとんどの操作を行うことができます。
このチェックルーチンは木に挿入すべきノードを返します(トップレベルの ノードが変更されていなければ、チェックルーチンはその引数を返します)。
規約により、チェックルーチンは ck_*
のような名前を持ちます。 これらは通常サブルーチン new*OP
(もしくは convert
) から 呼び出されます(これらのサブルーチンは perly.y から呼び出されます)。
チェックルーチンが呼び出された直後に、返されたノードはコンパイル時実行の ためのチェックが行なわれます。 もしそうであれば(値が定数であると判定された)、そのノードは即座に実行されて、 「戻り値」に対応する部分木は 定数 ノードで置換され、部分木が削除されます。
定数の畳み込み(constant folding)が働かなければ、実行順序スレッドが 生成されます。
解析木の一部分のコンテキストがわかっているとき、それは木の末端へ伝播します。 このとき、コンテキストは(実行時コンテキストの二種類ではなく) 無効、真偽値、スカラ、リスト、左辺値の五種類の値を持つことができます。 パス 1 とは対照的に、このパスではトップから末端へと処理が進みます。 あるノードのコンテキストは、その下にある部分のコンテキストを決定します。
コンテキストに依存した最適化はこのときに行なわれます。 この動作では解析木が(“スレッド”ポインタを通じて)後方参照を含んでいるので、 ノードをこの時に free() することはできません。 このステージでノードを最適化するのを許すために、対象となるノードは free() されるかわりに null() されます(つまり、そのノードの型が OP_NULL に 変えられるということ)。
サブルーチン(もしくは eval
かファイル)に対する解析木が生成された後で、 そのコードに対する追加パスが実行されます。 このパスはトップダウンでもボトムアップでもなく、(条件に対する複雑さを伴った) 実行順序です。 これらの最適化はサブルーチン peep() で行なわれます。 このステージで行なわれる最適化はパス 2 でのものと同じ制限に従います。
コンパイル木は runops 関数で実行されます。 run.c と dump.c に二つの関数があります。 Perl_runops_debug
は DEBUGGING で使われ、Perl_runops_standard
は その他で使われます。 コンパイル木の実行を細かく制御するために、独自の runops 関数を 設定できます。
既にある runops 関数の一つをコピーして、必要性に合わせて変更するのが おそらく最良です。 それから、XS ファイルの BOOT セクションに、以下の行を追加します:
PL_runops = my_runops;
この関数はプログラムを出来るだけ早く実行し続けられるように、出来るだけ 効率的にするべきです。
dump
関数で調べるデバッグを助けるために、ソースファイル dump.c に内部データ構造の フォーマットした出力を生成する多くの関数があります。
これらの関数で最もよく使われるものは Perl_sv_dump
です; これは SV, AV, HV, CV をダンプするために使います。 Devel::Peek
モジュールは、Perl 空間からのデバッグ出力を作成するために sv_dump
を呼び出すので、このモジュールのユーザーは既にこのフォーマットに 親しみがあるはずです。
Perl_op_dump
は、OP
構造体やその派生をダンプするために使い、 perl -Dx
と同様の出力を作成します; 実際のところ、Perl_dump_eval
は -Dx
と正確に同じように、評価されたコードの main ルートをダンプします。
その他の有用な関数は、GV
を op 木に変換する Perl_dump_sub
と、 パッケージの全てのサブルーチンで Perl_dump_sub
を呼び出す Perl_dump_packsubs
: (ありがたいことに、これらは全て xsub なので、 op 木はありません)
(gdb) print Perl_dump_packsubs(PL_defstash)
SUB attributes::bootstrap = (xsub 0x811fedc 0)
SUB UNIVERSAL::can = (xsub 0x811f50c 0)
SUB UNIVERSAL::isa = (xsub 0x811f304 0)
SUB UNIVERSAL::VERSION = (xsub 0x811f7ac 0)
SUB DynaLoader::boot_DynaLoader = (xsub 0x805b188 0)
および、stash の全てのサブルーチンと main ルートの op 木をダンプする Perl_dump_all
です。
Perl インタプリタはブラックボックスとして扱われます: コードに与えたり、 何かをするための API がありますが、自分自身で使うための関数もあります。 これはオブジェクトのような匂いがして、それぞれを C の構造体や スレッド固有の構造体の内部として表現する、複数のインタプリタを使えるように Perl をビルドするための方法があります。 これらの構造体はそのインタプリタの全てのコンテキストと状態を含みます。
一つのマクロは主な Perl ビルド設定: MULTIPLICITY です。 MULTIPLICITY ビルドは全てのインタプリタ状態をパッケージした C の構造体を 持ちます。 MULTIPLICITY を遊行した perl では、PERL_IMPLICIT_CONTEXT も普通設定され、 三つのデータ構造体全てを表現する「隠された」最初の引数を渡すことへの 対応が有効になります。 MULTIPLICITY は(マクロ USE_ITHREADS に関連する ithread スレッドモデルで) マルチスレッド perl を可能にします。
あと二つの「カプセル化」マクロは PERL_GLOBAL_STRUCT と PERL_GLOBAL_STRUCT_PRIVATE です(後者は前者を有効にして、前者は MULTIPLICITY を有効にします。) PERL_GLOBAL_STRUCT は Perl の全ての内部変数を一つグローバル構造体である struct perl_vars にラップして、(グローバルに) &PL_Vars, PL_VarsPtr, Perl_GetVars() 関数でアクセスできます。 PERL_GLOBAL_STRUCT_PRIVATE はもう一歩進めて、やはり(main() でヒープか スタックに割り当てられた)一つの構造体ですが、これを示すグローバルな データシンボルはありません。 どちらの場合でもグローバルな構造体は Perl_init_global_struct() を使って main() の最初で初期化され、Perl_free_global_struct() を使って perl_free() の 後で解放されます; 詳細な使用法については miniperlmain.c を 参照してください。 これらを使う時、「グローバル変数を宣言する」ためにコード中で dVAR
を 使う必要があるかもしれません。 dTHX はこれを自動的に行います。
非 const データがあるかどうかを見るには、BSD 互換の nm
を使えます:
nm libperl.a | grep -v ' [TURtr] '
D
または d
シンボルが表示されたら、非 const データがあります。
後方互換性のために、単に PERL_GLOBAL_STRUCT を定義しただけでは 大きなグローバル構造体の全てのシンボルは隠れません: いくつかの PerlIO_xxx vtables は見えるままです。 PERL_GLOBAL_STRUCT_PRIVATE は全てを隠します ( PERLIO_FUNCS_DECL の 使い方を参照してください)。
これら全ては明らかに、Perl 内部関数を、ある種の構造体を最初の引数として取る サブルーチンか、最初の引数に何も取らないサブルーチンにする方法が 必要です。 インタプリタのビルドをかなり異なった方法でこれら二つを有効にするために、 Perl ソースは(その他の多くの状況で行うのと同様) マクロとサブルーチンの 命名規則を激しく使っています。
最初の問題: どの関数が公的な API 関数になる関数で、どの関数が プライベートかを決定する。 名前が S_
で始まる全ての関数はプライベートです ("S" は "secret" または "static" と考えてください)。 その他の全ての関数は "Perl_" で始まりますが、"Perl_" で始まっているからと いって API の一部とは限りません。 ("Internal Functions" を参照してください。) 関数が API の一部であることを 確認する 最も簡単な方法は、 perlapi からエントリを探すことです。 もし perlapi にあれば、API の一部です。 もしなくて、あなたが これは API であるべきと考える(つまり、あなたの エクステンションに必要)なら、どうしてそう考えるかを説明したメールを perlbug で送ってください。
二番目の問題: 同じサブルーチン定義と呼び出しが最初の引数として構造体を 渡せるようにするか、何も渡さないようにする文法でなければなりません。 問題を解決するために、サブルーチンは決められた方法で命名して宣言されます。 以下は、Perl の内部で使われている静的関数の典型的な開始部分です:
STATIC void
S_incline(pTHX_ char *s)
STATIC は C では "static" になり、将来一部の設定では何もしないように #define されます。
公的な関数(つまり内部 API の一部ですが、エクステンションで使うのに許可は 不要なもの)は以下のように始まります:
void
Perl_sv_setiv(pTHX_ SV* dsv, IV num)
pTHX_
は、インタプリタのコンテキストの詳細を隠すための(perl.h にある) 多くのマクロの一つです。 THX は "thread", "this", "thingy" などから来ています。 (そしてジョージルーカスは関係ありません。:-) 最初の文字は 'p' がプロトタイプ(prototype)、'a' が引数(argument)、 'd' が宣言(declaration) を意味するので、pTHX
, aTHX
, dTHX
および その変形があります。
PERL_IMPLICIT_CONTEXT が設定されたオプションなしで Perl がビルドされると、 インタプリタのコンテキストに最初の引数は含まれません。 pTHX_ マクロの末尾の下線は、他の引数が引き続くのでマクロ拡張はコンテキスト 引数の後にカンマが必要であることを示しています。 PERL_IMPLICIT_CONTEXT が定義されていない場合、pTHX_ は無視され、 サブルーチンは追加の引数を取るようなプロトタイプを持ちません。 引き続く下線なしのマクロの形式は、追加の明示的な引数がない場合に使われます。
コア関数が他の関数を呼び出すとき、コンテキストを渡さなければなりません。 これは普通マクロ経由で隠されます。 sv_setiv
を考えてみます。 これは以下のような感じに展開されます:
#ifdef PERL_IMPLICIT_CONTEXT
#define sv_setiv(a,b) Perl_sv_setiv(aTHX_ a, b)
/* can't do this for vararg functions, see below */
#else
#define sv_setiv Perl_sv_setiv
#endif
これはうまく動きますし、XS 作者は喜んで以下のように書けます:
sv_setiv(foo, bar);
そしてやはり Perl がコンパイルされる全てのモードで動作します。
しかし、可変長関数ではそれほどきれいには動作しません; マクロは事前に 引数の数が分かっていることを仮定しているからです。 どちらかを完全に綴る必要があるようにする代わりに、最初の引数として aTHX_
を渡す(Perl コアは Perl_warner のような関数でこれをする 傾向があります)か、コンテキストの影響を受けないバージョンを使います。
Perl_warner のコンテキストの影響を受けないバージョンは Perl_warner_nocontext と呼ばれ、追加の引数を取りません。 代わりに、スレッドローカルなストレージからコンテキストを得るために dTHX; します。 エクステンションが性能のコストでソース互換性を得るために #define warner Perl_warner_nocontext
とします。 (一つの引数を渡すのはスレッドローカルなストレージから値を取り出すよりも 安価です。)
Perl ヘッダ/ソースを見るときには [pad]THXx を無視できます。 これらは純粋にコア内部での使用のためのものです。 エクステンションと組み込みだけが [pad]THX の存在を汁必要があります。
dTHR
は、古いスレッドモデルに対応するために perl 5.005 で 導入されました。 古いスレッドモデルは今ではコンテキストのポインタを渡すのに THX
機構を 使うので、dTHR
はもはや有用ではありません。 Perl 5.6.0 以降では、ソースの後方互換性のためにまだ存在していますが、 何もしないように定義されています。
Perl が PERL_IMPLICIT_CONTEXT 付きでビルドされると、Perl API の 関数を呼び出すエクステンションは何か初期コンテキスト引数を渡す必要が あります。 キッカーは、Perl が PERL_IMPLICIT_CONTEXT を有効にせずにビルドされたときにも エクステンションがコンパイルできるようにそれを書く方法が必要ということです。
これをするには三つの方法があります。 最初に、簡単だけれども効率的ではない方法ですが、エクステンションのソース 互換性を維持するために、これがデフォルトです: XSUB.h が #include されると、 コンテキストを返す関数を呼び出すように aTHX と aTHX_ のマクロを 再定義します。 従って、以下のようなものが:
sv_setiv(sv, num);
エクステンションにあると、PERL_IMPLICIT_CONTEXT が有効なら、以下のように 翻訳します:
Perl_sv_setiv(Perl_get_context(), sv, num);
さもなければ、こうなります:
Perl_sv_setiv(sv, num);
これをするためにエクステンション何の新しいこともする必要はありません; Perl ライブラリは Perl_get_context() を提供するので、全てうまく 動作します。
次に、より効率的な方法は、Foo.xs に以下のテンプレートを使うことです:
#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
STATIC void my_private_function(int arg1, int arg2);
STATIC void
my_private_function(int arg1, int arg2)
{
dTHX; /* fetch context */
... call many Perl API functions ...
}
[... etc ...]
MODULE = Foo PACKAGE = Foo
/* typical XSUB */
void
my_xsub(arg)
int arg
CODE:
my_private_function(arg, 10);
エクステンションを書く通常の方法とただ二つの違いは、Perl ヘッダを インクルードする前に #define PERL_NO_GET_CONTEXT
を追加して、 Perl API を呼び出す全ての関数の先頭に dTHX;
宣言を書くということに 注意してください。 (どの関数にこれが必要なのかは分かります; これらの関数に未宣言の識別子が あると C コンパイラがエラーを出すからです。) XSUB 自身には変更は必要荒れません; なぜなら XS() マクロは、もし必要なら 暗黙のコンテキストを渡すように正しく定義されるからです。
3 番目に、さらに効率的な方法は、Perl の内部で行われている方法を 真似ることです:
#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
/* pTHX_ only needed for functions that call Perl API */
STATIC void my_private_function(pTHX_ int arg1, int arg2);
STATIC void
my_private_function(pTHX_ int arg1, int arg2)
{
/* dTHX; not needed here, because THX is an argument */
... call Perl API functions ...
}
[... etc ...]
MODULE = Foo PACKAGE = Foo
/* typical XSUB */
void
my_xsub(arg)
int arg
CODE:
my_private_function(aTHX_ arg, 10);
この実装は、関数呼び出しを使ってコンテキストを取得する必要はありません; なぜなら常に追加の引数として渡されるからです。 単純さと効率性のどちらが必要かに応じて、前述の二つの手法と自由に 混ぜてもかまいません。
pTHX
の後ろに自分でカンマを追加しないでください -- 明示的な引数を 取る関数の場合は下線のあるマクロの形式を、明示的な引数のない関数では 引数なしの形式を、常に使ってください。
-DPERL_GLOBAL_STRUCT
付きで Perl をコンパイルすると、Perl グローバル変数 (perlvars.h や globvar.sym を参照)が関数内でアクセスされて、 dVAR
が使われない(dTHX
は、必要なら dVAR
をインクルードします)場合、 dVAR
定義が必要です。 dVAR
の必要性はコンパイル時の定義でのみ気付きます; なぜならさもなければ Perl グローバル変数はそのまま見えるからです。
あるスレッドでインタプリタを作成して、それから他のスレッドでそれを 呼び出そうとするなら、perl の独自のスレッドローカルストレージ (Thread Local Storage (TLS)) スロットがそれぞれのスレッドで正しく 初期化されるようにする必要があります。
perl_alloc
と perl_clone
の API 関数は、作成されたインタプリタへの TLS スロットを自動的に設定するので、インタプリタを作成したスレッドと 同じスレッドでだけ使って、そのスレッドがその後他のインタプリタを作成したり 呼び出したりしないのなら、何も特別なことをする必要はありません。 そうでない場合、特定のインタプリタの Perl API の関数を呼び出す前に、 そのスレッドの TLS スロットを設定する必要があります。 これは、そのスレッドで最初にすることとして PERL_SET_CONTEXT
マクロを 呼び出すことで行われます:
/* do this before doing anything else with some_perl */
PERL_SET_CONTEXT(some_perl);
... other Perl API calls on some_perl go here ...
PERL_IMPLICIT_CONTEXT が、インタプリタが自分自身および渡されたものに関して 知っていること全てをまとめる方法を提供しているのとちょうど同じように、 インタプリタが自分が実行している環境について知っている全てを まとられるようにする計画があります。 これは PERL_IMPLICIT_SYS マクロで有効にされます。 現在のところ、これは Windows で USE_ITHREADS 付きの場合にのみ動作します。
これにより、全てのシステムコールのための(「ホスト」環境と呼ばれる) 追加のポインタを提供する能力を持つようになります。 これにより、独自の状態を保守する全てのシステムの機能について、七つの C 構造体に分解することが可能になります。 デフォルトの perl 実行ファイルのために、通常のシステムコールへの 薄いラッパです (win32/perllib.c を参照してください) が、 (fork() エミュレーションを行うような)より意欲的なホストのために、 異なるインタプリタが実際には異なる「プロセス」であることを装うために 必要になる全ての作業は、ここで行われます。
Perl エンジン/インタプリタとホストは直交する概念です。 一つのプロセスに複数のインタプリタがあることもありますし、複数の「ホスト」が 互いに自由に関連しながらあることもあります。
外部の世界に曝されている Perl の内部関数の全ては Perl_
の接頭辞が ついているので、XS 関数や Perl が組み込まれている関数で使われている関数と 衝突しません。 同様に、全てのグローバル変数は PL_
で始まります。 (慣例的に、静的関数は S_
で始まります。)
Perl コアの内側では、embed.h にあるたくさんの define のおかげで、 Perl_
接頭辞ありとなしのどちらかの関数を使えます。 このヘッダファイルは embed.pl と embed.fnc から自動的に生成されます。 embed.pl は内部関数のためのヘッダファイルのプロトタイプも作成し、 その他の多くの欠片の文書も生成します。 新しい関数をコアに追加したり既にあるものを変更したりした場合、 embed.fnc にある表のデータも変更することが重要です。 以下はその表のエントリの例です:
Apd |SV** |av_fetch |AV* ar|I32 key|I32 lval
2 番目の列は返り値型で、3 番目の列は名前です。 それ以降の列は引数です。 最初の列はフラグの集合です:
この関数は公式 API の一部です。 このような関数全ては 'd' も持っているべきですが、ごく一部は違います。
この関数は Perl_
接頭辞を持っています; つまり、Perl_av_fetch
として 定義されています。
この関数は、すぐに見られる apidoc
機能を使った文書があります。 一部の関数は 'd' ですが 'A' ではありません; 文書はよいものです。
その他の利用可能なフラグは:
これは静的関数で、STATIC S_whatever
として定義されており、普通は ソース中で whatever(...)
として呼び出されます。
これはインタプリタのコンテキストを必要としないので、定義には pTHX
はなく、 呼び出し元は aTHX
を使いません。 ("Background and PERL_IMPLICIT_CONTEXT" in perlguts を参照してください。)
この関数は返りません; croak
, exit
のようなものです。
この関数は printf
形式の可変長の引数を取ります。 引数のリストは以下のように ...
で終わります:
Afprd |void |croak |const char* pat|...
この関数は実験的開発 API の一部で、注意なしに変更されたり消滅したり するかもしれません。
この関数は、Perl_parse
から parse
のような定義されている互換性マクロを 持っていません。 これは Perl_parse
として呼び出されなければなりません。
この関数は Perl コアの外側へエクスポートされません。
これはマクロとして実装されています。
この関数は明示的にエクスポートされます。
この関数は Perl コアに含まれるエクステンションから見えます。
バイナリ後方互換性; この関数はマクロですが、(エクスポートされている) Perl_
実装もあります。
その他については embed.fnc
の先頭のコメントを参照してください。
embed.pl または embed.fnc を編集した場合、embed.h およびその他の 自動生成ファイルを強制的にリビルドするために make regen_headers
を 実行する必要があります。
IV, UV, NVS を、stdio(3) 形式の %d
, %ld
, %f
のような フォーマッティングコードではなく表示したいなら、互換性のために以下の マクロを使うべきです
IVdf IV in decimal
UVuf UV in decimal
UVof UV in octal
UVxf UV in hexadecimal
NVef NV %e-like
NVff NV %f-like
NVgf NV %g-like
これらは 64 ビット整数や long double も考慮します。 例えば:
printf("IV is %"IVdf"\n", iv);
IVdf は、なんであれ IV のための正しいフォーマットに拡張されます。
ポインタのアドレスを表示したいなら、PTR2UV() で UVxf を使ってください; %lx や %p は使わないでください。
ポインタサイズは整数のサイズと同じである必要はないので、正しく行うために 以下のマクロを使ってください。
PTR2UV(pointer)
PTR2IV(pointer)
PTR2NV(pointer)
INT2PTR(pointertotype, integer)
例えば:
IV iv = ...;
SV *sv = INT2PTR(SV*, iv);
および
AV *av = ...;
UV uv = PTR2UV(av);
XS モジュールでのとても基本的な例外処理を行うためのいくつかのマクロが あります。 これらのマクロを使えるようにするために XSUB.h をインクルードする前に NO_XSLOCKS
を定義する必要があります:
#define NO_XSLOCKS
#include "XSUB.h"
croak するかもしれないコードを呼び出すときにこれらのマクロが使えますが、 Perl に制御を戻す前に一部掃除掃除をする必要があります。 例えば:
dXCPT; /* set up necessary variables */
XCPT_TRY_START {
code_that_may_croak();
} XCPT_TRY_END
XCPT_CATCH
{
/* do cleanup here */
XCPT_RETHROW;
}
捕捉した例外を常に再スローする必要があることに注意してください。 これらのマクロを使って、単に例外を捕捉して無視することはできません。 例外を無視する必要があるなら、call_*
関数を使う必要があります。
上述のマクロを使う利点は、call_*
のための追加の関数を設定する 必要がないことと、これらのマクロを使うと call_*
を使うよりも 高速であることです。
内部関数の文書を書いて、そこからリファレンスマニュアルを自動的に 生成しようという作業が行われています - perlapi はその一つで、XS 作者が 利用可能な全ての関数の詳細に関するマニュアルです; perlintern は、API の一部ではなく、内部使用専用と想定されている関数の 自動生成マニュアルです。
ソース文書は、以下のように、C ソースに POD コメントを書くことで 作成されます:
/*
=for apidoc sv_setiv
Copies an integer into the given SV. Does not handle 'set' magic. See
C<sv_setiv_mg>.
=cut
*/
Perl コアに関数を追加するなら、文書を書いて提供するようにしてください。
Perl API は時が経つにつれて変わります。 新しい関数が追加されたり、既にある関数のインターフェースが 変更されたりします。 Devel::PPPort
モジュールはこれらの変更の一部に関して互換コードを 提供しようとするので、XS 作者は複数バージョンの Perl に対応するときに そのためのコードを自分自身で作る必要はありません。
Devel::PPPort
は、Perl スクリプトとしても実行される C ヘッダファイル ppport.h を生成します。 ppport.h を生成するには、以下のものを実行します:
perl -MDevel::PPPort -eDevel::PPPort::WriteFile
既にある XS コードをチェックするほかに、このスクリプトは、--api-info
コマンドラインオプションを使うことで、様々な API 呼び出しの互換性情報を 取得するのにも使えます。 例えば:
% perl ppport.h --api-info=sv_magicext
詳細については、perldoc ppport.h
を参照してください。
Perl 5.6.0 から Unicode 対応が導入されました。 porters と XS 作者にとって、この対応を理解して、書いたコードが Unicode データを壊さないようにすることは重要です。
古く、あまり啓蒙されていなかった時代、私たち全ては ASCII を使っていました。 とりあえず、私たちのほとんどはそうでした。 ASCII の大きな問題は、これは英語だったことです。 えっと、これは本当の問題ではありません; 問題は、英文字を使わない 人々にとっては特に有用ではないということです。 起こったことは、ある種の言語は独自のアルファベットを並びの上半分、 128 から 255 にくっつけるということでした。 もちろん、結局完全に ASCII ではないものの変種だらけになり、標準となるものは 失われました。
さらに悪いことに、数百または数千の文字がある中国語や日本語のような言語を 使うとき、これらを単に 256 に納めるのは不可能なので、ASCII を完全に 忘れてしまって、一つの文字を参照するのに二つの数の組み合わせを使う 独自のシステムを構築しました。
これを修正するために、一部の人々は Unicode, Inc. を作り、考えられる全ての 文字以上のものを含む新しい文字集合を作成しました。 これらの文字を表現するにはいくつかの方法があり、Perl が使うものは UTF-8 と呼ばれます。 UTF-8 は 1 文字を表現するのに可変の数のバイトを使います。 Unicode と Perl の Unicode モデルについては、perlunicode で学べます。
出来ません。 これは、UTF-8 データは非 UTF-8 データと同じようにバイトとして 保管されるからです。 Unicode 文字 200 (16 進数で書くなら 0xC8
) である、 大文字 E(重アクセント記号付) は 2 バイト v196.172
で表現されます。 残念ながら、非 Unicode 文字列 chr(196).chr(172)
も同じバイト並びを 持ちます。 従って、見ただけで判断することは出来ません - これが Unicode 入力を 興味深い問題にしているものです。
一般的に、どうやって扱うかを知るか、推測するかのどちらかが必要です。 API 関数 is_utf8_string
が助けになります; これは、文字列が有効な UTF-8 文字列のみを含んでいるかを返します。 しかし、これはあなたのための作業は出来ません。 文字単位では、is_utf8_char
は文字列中の現在の文字が有効な UTF-8 かどうかを返します。
上述したように、UTF-8 は文字を格納するのに可変の数のバイトを使います。 値 0...127 の文字はちょうど ASCII と同じように 1 バイトで保管されます。 文字 128 は v194.128
として保管されます; これは 文字 191 v194.191
まで 続きます。 ここでビットがなくなるので (191 は 2 進数では 10111111
)、次に進みます; 192 は v195.128
です。 このように進んでいき、文字 2048 では 3 バイトになります。
UTF-8 文字列の扱い方を知っていると仮定すると、最初の文字の長さは UTF8SKIP
マクロで知ることができます:
char *utf = "\305\233\340\240\201";
I32 len;
len = UTF8SKIP(utf); /* len is 2 here */
utf += len;
len = UTF8SKIP(utf); /* len is 3 here */
UTF-8 文字列で文字をスキップするもう一つの方法は、utf8_hop
を使うことで、 これは文字列とスキップする文字数を取ります。 しかし、独自でも境界チェックは出来るので、これを軽率に使わないでください。
マルチバイト UTF-8 文字の全てのバイトは最上位ビットが設定されているので、 このようにこの文字に何か特別のことをする必要がある場合は、これで テストできます(UTF8_IS_INVARIANT() は、たとえ UTF-8 であったとしても 単一のバイトでエンコードされているかどうかをテストします):
U8 *utf;
UV uv; /* Note: a UV, not a U8, not a char */
if (!UTF8_IS_INVARIANT(*utf))
/* Must treat this as UTF-8 */
uv = utf8_to_uv(utf);
else
/* OK to treat this character as a byte */
uv = *utf;
この例では、文字の値を得るために utf8_to_uv
を使うところも見られます; 逆関数 uv_to_utf8
は、UV を UTF-8 にするのに使えます:
if (!UTF8_IS_INVARIANT(uv))
/* Must treat this as UTF8 */
utf8 = uv_to_utf8(utf8, uv);
else
/* OK to treat this character as a byte */
*utf8++ = uv;
UTF-8 文字列と非 UTF-8 文字列のマッチングをする必要がある場合は、上述の 関数を使って UV に変換 しなければなりません 。 このような場合では UTF-8 文字列を読み飛ばすことはできません。 これをすると、最上位ビットの立った非 UTF-8 文字をマッチングする能力を 失います; 例えば、UTF-8 文字列に v196.172
が含まれていて、この文字を スキップすると、非 UTF-8 文字列の chr(200)
にマッチングできません。 従って、そうしないでください!
現在のところ、Perl は Unicode 文字列と非 Unicode 文字列を少し違う形で 扱います。 SV のフラグ SVf_UTF8
は、文字列が内部で UTF-8 で エンコードされていることを示します。 これがない場合は、バイトの値が符号位置で、逆も成り立ちます (言い換えると、 文字列は iso-8859-1 としてエンコードされます)。 以下のマクロでこのフラグのチェックと操作ができます:
SvUTF8(sv)
SvUTF8_on(sv)
SvUTF8_off(sv)
このフラグは、Perl の文字列の扱いに重要な効果があります: Unicode データが 適切に識別されないと、正規表現、length
、substr
およびその他の 文字列操作演算子が想定外の結果となります。
問題は、例えば、UTF-8 としてフラグが経っていない文字列と、UTF-8 になり得る バイト並びがある時に起こります - 特に非 UTF-8 文字列と UTF-8 文字列を 結合するときに起こります。
SVf_UTF8
フラグは PV の値とは分かれていることを決して忘れないでください; SV の捜査中に間違ってオフにしないように注意する必要があります。 より具体的には、以下のようにすることは想定できません:
SV *sv;
SV *nsv;
STRLEN len;
char *p;
p = SvPV(sv, len);
frobnicate(p);
nsv = newSVpvn(p, len);
char*
文字列は一部始終を示しはせず、単に文字列の値をコピーするだけでは SV のコピーや再構成は出来ません。 もし古い SV の UTF8 フラグがセットされているかどうかを調べて、それに従って 行動します:
p = SvPV(sv, len);
frobnicate(p);
nsv = newSVpvn(p, len);
if (SvUTF8(sv))
SvUTF8_on(nsv);
実際、frobnicate
関数は、文字列を適切に扱えるようにするために、 UTF-8 データを扱えるかどうかが分かるようにするべきです。
単に XS 関数に SV を渡して、SV のデータをコピーするだけでは、 UTF8 フラグをコピーするのは不十分です; 正しいのが char *
を XS 関数に 渡すことでもです。
UTF-8 と non-UTF-8 の文字列を混ぜるなら、文字列の片方を UTF-8 に 昇格させる必要があります。 SV を使っているなら、これをするのに最も簡単な方法は:
sv_utf8_upgrade(sv);
しかし、例えば以下のようにしてはいけません:
if (!SvUTF8(left))
sv_utf8_upgrade(left);
これを二項演算子で行うなら、演算子から来る文字列の一つを実際に変更し、 エンドユーザーは気がつくべきではない一方、不完全なコードによる 問題を引き起こすかもしれません。
代わりに、bytes_to_utf8
は、文字列引数を UTF-8 でエンコードした コピー を作ります。 これは、元の SV に影響を与えることなく、比較などに使えるデータを作るのに 有用です。 また、逆方向を自然に行う utf8_to_bytes
もあります; これは文字列に 単一バイトで表現できない、番号 255 を超える文字が含まれていると 失敗します。
実際にはありません。 単に以下のことを覚えておいてください:
文字列が UTF-8 かどうかを知らせる方法はありません。 SV が UTF-8 であるなら SvUTF8
フラグを見ることで分かります。 何かが UTF-8 であるべきならフラグを設定することを忘れないでください。 たとえそうでなくても、このフラグを PV の一部として扱ってください - PV を どこかに渡すときは、このフラグも渡してください。
文字列が UTF-8 なら、値を得るときは 常に utf8_to_uv
を使ってください; 但し、UTF8_IS_INVARIANT(*s)
の場合は *s
を使えます。
文字 uv
を UTF-8 文字列を書き込むときは 常に uv_to_utf8
を 使ってください; 但し、UTF8_IS_INVARIANT(uv))
の場合は *s = uv
を 使えます。
UTF-8 と 非 UTF-8 の文字列を混ぜるのはトリッキーです。 UTF-8 エンコードされた新しい文字列を得るには bytes_to_utf8
を 使ってください。 UTF-8 文字列を使う必要があるかを決定するのを、最上位ビットが立った 文字が来るまで遅延するのに使えるトリックがあります - HALF_UPGRADE
は その一つです。
カスタム演算子対応は独自の op を定義できる新しい実験的機能です。 これは主に Perl コアに他の言語のためのインタプリタを 構築できるようにするためのものですが、「マクロ op」 (gvsv, gvsv, add
のように、普段一緒に実行される複数の op の関数を 実行する op) を作成することで最適化できるようにもします。
この機能は 新しい op 型である OP_CUSTOM
として実装されています。 Perl コアはこの op 型について何も特別なことは「知りません」し、 どのような最適化も行いません。 これはまた、どのような op 構造 - 単項、二項、リストなど - でも 好きなものになれるカスタム op を定義できるということです。
カスタム演算子がしないことを知ることは重要です。 これは Perl に直接新しい文法を追加するものではありません。 これは直接新しいキーワードを追加するものではありません。 実際のところ、Perl がプログラムする方法を何も変えません。 これらの変更は、Perl がプログラムをコンパイルした後、自分でする 必要があります。 これは、CHECK
ブロックと B::Generate
モジュールを使って op 木を 操作するか、optimize
モジュールでカスタム覗き穴最適化器を追加することで 行います。
これを行うとき、OP_CUSTOM
型と独自の PP 関数の pp_addr
を持つ カスタム op を作成して、普通の Perl op を置き換えます。 これは XS コードで定義されるべきで、pp_*.c
の PP op のように 見えるべきです。 作成した op がスタックから適切な数の値を取ることと、必要ならスタックに マークを追加することは作成者が責任を持ちます。
また、Perl インタプリタに作成した op を「登録」して、適切なエラーと 警告メッセージを生成できるようにします。 一つの「論理」op 型 OP_CUSTOM
に複数のカスタム op を 含めることができるので、Perl は PL_custom_op_descs
と PL_custom_op_names
ハッシュのキーとして o->op_ppaddr
の値を 使います。 これは、PL_custom_op_names
と PL_custom_op_descs
ハッシュの適切な 位置に作成した op の名前と説明を登録する必要があるということです。
リリース予定のバージョンの B::Generate
(バージョン 1.0 以上) では 名前によるカスタム op の作成に直接対応しています。
1997 年 5 月まで、この文書は Jeff Okamoto <okamoto@corp.hp.com> によって保守されていました。 今では Perl 自身の一部として Perl 5 Porters <perl5-porters@perl.org> によって保守されています。
Dean Roehrich, Malcolm Beattie, Andreas Koenig, Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil Bowers, Matthew Green, Tim Bunce, Spider Boardman, Ulrich Pfeifer, Stephen McCamant, Gurusamy Sarathy から多くの助けと示唆を受けました。
perlapi(1), perlintern(1), perlxs(1), perlembed(1)