NAME

perlguts - Perl API の紹介

DESCRIPTION

このドキュメントでは Perl API の使い方、および Perl コアの基本的な動作に 関するいくばくかの情報を提供しようとしています。 完璧からは程遠いものですし、間違いも多いと思います。 疑問点やコメントは後述する著者に対して行なってください。

変数

データ型

Perl では、主となる三つのデータ型を扱うために三つの型定義を行なっています:

    SV  Scalar Value
    AV  Array Value
    HV  Hash Value

それぞれの typedef には様々なデータ型を操作するための特別なルーチンが 用意されています。

"IV" ってなに?

Perl では、符号付き整数でもポインタでも十分に入れることのできる特別な typedef である IV を使います。 更に、単に符号なしの IV である UV もあります。

Perl はまた、二つの特殊な typedef である I32 と I16 を使っています; これらはそれぞれ、常に最低 32bit、16bit の長さを持っているものです。 (再び、同様に U32 と U16 もあります。) これらは普通は正確に 32 ビットと 16 ビットですが、Cray では両方とも 64 ビットです。

SV に対する作業

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_setpvnnewSVpv、あるいは newSVpv を使って指定することもできますし、sv_setpv を使ったり newSVpv の第二引数に 0 を指定することによって、Perl 自身に 文字列の長さを計算させることもできます。 ただし Perl は、NUL 文字で終了していて、それ以外に NUL が 含まれていないということに依存している strlen を使って長さを 計算しているということに注意してください。

sv_setpvf の引数は sprintf と同じように処理され、書式化された 出力が値となります。

sv_vsetpvfnvsprintf と同じようなものですが、可変引数リストに対する ポインタか SV の配列のアドレスと長さのいずれかを指定することができます。 最後の引数は真偽値を指し示します; 関数から返ってきたときにこれが 真であれば、フォーマット文字列としてロケール固有の情報が使われているので その文字列の内容は信頼するできないことを表わしています(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_naSvPV マクロが 使われてきました。 しかしこれは可能ですが効率は良くありません; なぜなら 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", 0);

これは変数が存在していない場合には 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_yesPL_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 ポインタを移動させて、SvCURSvLEN を調整します。

従って、この時点で、割り当てられたバッファの先頭はメモリ中の 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 は これがオフセットであることを示す助けをしてくれます。 「実際」と「偽物」の開始の間の文字列の部分はかっこで示され、 SvCURSvLEN の値は実際のものではなく偽物の先頭を反映します。

オフセットハックと似たようなものは、配列の先頭の効率的なシフトと切り落としを 有効にするために AV に対しても行われます; AvARRAY は Perl から見える配列の最初の要素を指していますが、AvALLOC は C の配列の実際の先頭を指しています。 これらは普通は同じですが、shift 演算子は AvARRAY を一つ増やして、 AvFILLAvMAX を一つ減らします。 再び、C の配列の実際の先頭の一は、配列を解放するときにだけ使われます。 av.cav_shift を参照してください。

SV に実際に格納されているものは何ですか?

自分で保持しているスカラの型を決定する通常の方法は、マクロ 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 を作るものです:

    AV*  newAV();

ふたつめの方法は、AV を生成した上で、初期値として SV の値を入れます:

    AV*  av_make(I32 num, SV **ptr);

二番目の引数は num 個の SV* の配列を指しています。 AV が生成されてしまえば、SV は(それを望むのなら)破棄することができます。

いったん 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_fetchav_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", 0);

これは変数が存在していない場合には NULL を返します。

tie された配列における配列アクセス関数の使い方についての詳細は "Understanding the Magic of Tied Hashes and Arrays" を参照してください。

HV に対する作業

HV を生成するには、以下のようなルーチンを使います:

    HV*  newHV();

いったん 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 で、このフェッチ操作が実はストア操作の一部であるかどうかを 示します; ストア操作であれば、新たな未定義値が与えられたキーを伴って HV に追加され、hv_fetch はその値が既に存在していたかのように リターンします。

hv_storehv_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);

flagG_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", 0);

これは変数が存在していない場合には 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" を参照してください。

ハッシュ API 拡張

バージョン 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_storehv_store_ent の両方ともが、val に格納されている 参照カウントのインクリメントをしないということに注意してください; それは呼び出し側の責任です。 これらの関数が NULL を返した場合、呼び出し側はメモリリークを防ぐために、 val の参照カウントのデクリメントを行う必要が一般にはあるでしょう。

AV, HV と未定義値

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_yes&PL_sv_no を AV や HV に保管するときにも同じような 問題が起こります。 このような要素を修正しようとすると、以下のようなエラーが出ます:

    Modification of a read-only value attempted

長い物語を短くすると、特殊変数 &PL_sv_undef, &PL_sv_yes, &PL_sv_no を 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_incthing の参照カウントを インクリメントするけれども newRV_noinc はインクリメントしないという点を 除き、同一です。 歴史的な理由により、newRVnewRV_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 を参照してください。

bless されたリファレンスとクラスオブジェクト

リファレンスはオブジェクト指向プログラミングをサポートするためにも使われます。 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, void* pv);

以下の関数は、文字列を rv が参照している SV へコピーします。 length に 0 を設定すると、Perl が文字列の長さを計算します。 SV は classname がヌルでなければ bless されます。

    SV* sv_setref_pvn(SV* rv, const char* classname, char* pv,
                                                         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)) { ... }

新しい変数の作成

Perl スクリプトからアクセスできる未定義値を持つ新たな Perl の変数を 生成するには、以下に示すルーチンを変数の型に応じて使います。

    SV*  get_sv("package::varname", GV_ADD);
    AV*  get_av("package::varname", GV_ADD);
    HV*  get_hv("package::varname", GV_ADD);

二番目のパラメータとして GV_ADD を使っているということに注意してください。 新しい変数はここでデータ型に対する適切なルーチンを使うことで設定できます。

GV_ADD 引数とビット和を取って、幾つかの追加機能を有効とするような 二つのマクロがあります。 ビットは以下の通りです:

GV_ADDMULTI

変数に多重定義 (multiply defined) であると印を付け:

  Name <varname> used only once: possible typo

警告を防ぎます。

GV_ADDWARN

以下の警告を:

  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 に依存しています。 これら二つのマクロについての説明は perlcallperlxs を参照してください。

「揮発化」("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_incsv_2mortal をするかどうかはっきりしないときは、 sv_mortalcopy を作るのがより安全です。

揮発性のルーチンは、単に SV のためだけではありません; AV や HV も、sv_2mortalsv_mortalcopy ルーチンに、アドレスを (SV* にキャストして) 渡すことで、揮発性にすることができます。

スタッシュとグロブ

スタッシュ ("stash")とは、パッケージ内で定義された全ての変数が 入っているハッシュのことです。 ハッシュテーブルにあるそれぞれの key は、(同じ名前のすべての異なる型の オブジェクトで共有される) シンボル名で、ハッシュテーブルの個々の 値は、(グローバル値のための) GV と呼ばれます。 GV には、以下のものを含む (これらに限りませんが)、その名前の様々な オブジェクトへのリファレンスが次々に入ることになります。

    Scalar Value
    Array Value
    Hash Value
    I/O Handle
    Format
    Subroutine

main パッケージにあるアイテムを保持する PL_defstash と呼ばれる スタッシュがあります。 他のパッケージにあるアイテムを取得するには、パッケージ名に「::」を付加します。 Foo というパッケージにあるアイテムは PL_defstash の Foo:: という スタッシュの中にあります。 パッケージ 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 を 参照してください。

二重型 SV

スカラ変数は通常、整数、倍精度、ポインタ、リファレンスのうちの いずれか一つの型をとります。 Perl は実際のデータに対して、蓄積されている型から要求されている型へ、 自動的に変換を行ないます。

ある種のスカラ変数は、複数の型のスカラデータを持つようになっています。 たとえば変数 $! は、errno の数値としての値と、 strerrorsys_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", GV_ADD);
    sv_setiv(sv, (IV) dberror);
    sv_setpv(sv, dberror_list[dberror]);
    SvIOK_on(sv);

sv_setivsv_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 は svSVt_PVMG に 変換するために SvUPGRADE を使います。 Perl はそれから、マジック機能のリンクリストの先頭にそれを追加します。 以前に存在していた同じタイプのマジックは削除されます。 これはオーバーライドすることができ、複数の同じ型のマジックのインスタンスを 一つの SV に結び付けることができるということに注意してください。

引数 namenamlen はある文字列と magic とを結び付けるために 使われます; 典型的には変数の名前です。 namlenmg_len フィールドに格納され、name がヌルなら、 namlen が 0 より大きいか、0 かに依存して、それぞれ namesavepvn コピーか、name 自身に保管されます。 特殊な場合として、(name && namlen == HEf_SVKEY) なら nameSV* を含んでいるものと仮定して 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' マジックを使っているものに出会うことがあるかもしれません。

引数 objMAGIC 構造体の mg_obj フィールドに格納されます。 これが sv 引数と同じでなかった場合、obj の参照カウントは インクリメントされます。 同じであった場合、もしくは引数 howPERL_MAGIC_arylen かヌルポインタであった場合には、obj は 参照カウントのインクリメントをさせることなく格納されます。

SV にマジックを追加する、より柔軟な方法については perlapisv_magicext も参照してください。

同様に HV にマジックを付加する関数があります。

    void hv_magic(HV *hv, GV *gv, int how);

これは単純に sv_magic を呼び出し、引数 gv を強制的に SV にします。

SV からマジックを取り除くには、sv_unmagic という関数を呼び出します。

    int sv_unmagic(SV *sv, int type);

引数 type は、SV が magical にされたときの how の値と同じに なるようにすべきです。

しかし、sv_unmagicSV から、ある type の全てのマジックを 削除することに注意してください。 マジック下層テーブルを基に type の特定のマジックのみを削除したい場合は、 代わりに sv_unmagicext を使ってください:

    int sv_unmagicext(SV *sv, int type, MGVTBL *vtbl);

マジック仮想テーブル

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, I32 namlen);
    int  (*svt_dup)(MAGIC *mg, CLONE_PARAMS *param);
    int  (*svt_local)(SV *nsv, MAGIC *mg);

この MGVTBL は perl.h の中でコンパイル時に設定され、現在 32 の型が あります。 これらの異なった構造体は、関数が呼び出されたときに依存して追加動作を 行うような様々なルーチンへのポインタを保持しています。

    関数ポインタ     その振る舞い
   ----------------    ------------
   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_svmg_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         特殊スカラ変数
 #  PERL_MAGIC_arylen         vtbl_arylen     配列の長さ ($#ary)
 %  PERL_MAGIC_rhash          (none)          制限ハッシュの追加データ
 .  PERL_MAGIC_pos            vtbl_pos        pos() 左辺値
 :  PERL_MAGIC_symtab         (none)          シンボルテーブルの追加データ
 <  PERL_MAGIC_backref        vtbl_backref    弱いリファレンス用
 @  PERL_MAGIC_arylen_p       (none)          arylen を XPVAV の外に動かす用
 A  PERL_MAGIC_overload       vtbl_amagic     %OVERLOAD ハッシュ
 a  PERL_MAGIC_overload_elem  vtbl_amagicelem %OVERLOAD ハッシュ要素
 B  PERL_MAGIC_bm             vtbl_regexp     Boyer-Moore (高速文字列検索)
 c  PERL_MAGIC_overload_table vtbl_ovrld      スタッシュのオーバーロード
                                              テーブル(AMT) を保持
 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_regdata    フォーム行(「コンパイル済み」
                                              フォーマット)
 G  PERL_MAGIC_study          vtbl_regexp     study() された文字列
 g  PERL_MAGIC_regex_global   vtbl_mglob      m//g のターゲット
 H  PERL_MAGIC_hints          vtbl_hints      %^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 要素
 N  PERL_MAGIC_shared         (none)          スレッド間で共有される
 n  PERL_MAGIC_shared_scalar  (none)          スレッド間で共有される
 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_regexp     事前コンパイルされた qr// 正規表現
 S  PERL_MAGIC_sig            (none)          %SIG ハッシュ
 s  PERL_MAGIC_sigelem        vtbl_sigelem    %SIG ハッシュ要素
 t  PERL_MAGIC_taint          vtbl_taint      汚染性
 U  PERL_MAGIC_uvar           vtbl_uvar       エクステンションで使用可能
 u  PERL_MAGIC_uvar_elem      (none)          エクステンションが使うために
                                              予約
 V  PERL_MAGIC_vstring        vtbl_vstring    SV はv-文字列リテラル
 v  PERL_MAGIC_vec            vtbl_vec        vec() 左辺値
 w  PERL_MAGIC_utf8           vtbl_utf8       キャッシュされた UTF-8 情報
 x  PERL_MAGIC_substr         vtbl_substr     substr() 左辺値
 y  PERL_MAGIC_defelem        vtbl_defelem    影の "foreach" 反復子
                                              変数 / スマート引数
                                              自動有効化
 ]  PERL_MAGIC_checkcall      (none)          この CV の呼び出しのインライン化/
                                              ミューテーション
 ~  PERL_MAGIC_ext            (none)          エクステンションで使用可能

テーブル中で大文字小文字の両方が存在していた場合、大文字は典型的には複合型 (リストもしくはハッシュ)の種類を表わすのに使われ、小文字はその複合型の 要素を表わすのに使われます。 内部コードにはこの大文字小文字の関係を使っているものもあります。 しかし、'v' と 'V' (ベクタと v-文字列) は全く関係がありません。

マジック型 PERL_MAGIC_extPERL_MAGIC_uvar はエクステンションから 使われ、Perl 自身からは使われないように特別に定義されています。 エクステンションは PERL_MAGIC_ext マジックを、 プライベート情報を変数(典型的なオブジェクト)に「アタッチ」(attach) するために使うことができます。 これは、通常の perl コードが(ハッシュオブジェクトの要素を使うのとは違って) そのプライベート情報を壊す恐れがないのでとても便利です。

同様に、PERL_MAGIC_uvar マジックは、スカラの値が使われたり 変更されたりしたときに C 関数を呼び出すという、tie() とよく似た形で使えます。 MAGICmg_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_extPERL_MAGIC_uvar マジックを 使う可能性があるので、エクステンションがそれを扱うには気をつけることが 重要であることに注意してください。 典型的には、これはオブジェクトをエクステンションが扱えるように同じクラスに bless するときにのみ使います。 PERL_MAGIC_ext マジックでは、たとえ全てのフィールドが 0 でも、 MGVTBL を定義するのが普通はよい考えです; 個々の MAGIC ポインタは それぞれのマジック仮想テーブルを使ったある種のマジックとして 識別されるからです。 mg_findext はそうするための簡単な方法を提供します:

    STATIC MGVTBL my_vtbl = { 0, 0, 0, 0, 0, 0, 0, 0 };

    MAGIC *mg;
    if ((mg = mg_findext(sv, PERL_MAGIC_ext, &my_vtbl))) {
        /* this is really ours, not another module's PERL_MAGIC_ext */
        my_priv_data_t *priv = (my_priv_data_t *)mg->mg_ptr;
        ...
    }

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 *sv, int type); /* Finds the magic pointer of that
                                       * type */

このルーチンは SV に格納されている MAGIC 構造体へのポインタを返します。 SV がマジカル機能を持っていなければ、NULL が返されます。 SV にマジカル機能を複数持っている場合、最初の物が返されます。 mg_findext は、マジック型とマジック仮想表の両方を元とする SV の MAGIC 構造体を探すのに使えます:

    MAGIC *mg_findext(SV *sv, int type, MGVTBL *vtbl);

また、mg_findmg_findext に渡された 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 されたハッシュと配列のマジックを理解する

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_storehv_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 を呼び出すだけです。 その後の mg_getmg_set の呼び出しは実際には元となっている オブジェクトへの TIE メソッドの起動を行います。 従って現在の所マジック機構は配列とハッシュへの一種の遅延アクセスを 実装しています。

現在(バージョン 5.004)、ハッシュや配列に対するアクセス関数を使用する 際には、ユーザーが「通常の」ハッシュや配列なのか、あるいはそれが tie されたものであるのかを気をつけることが要求されています。 将来のバージョンでは、この API は tie されたデータに対するアクセスと 通常のデータに対するアクセスをより透過的にするために変更されるかも しれません。 [/MAYCHANGE]

TIEARRAY や TIEHASH といったインターフェースが、統一的な ハッシュ/配列構文を使うための perl メソッドを起動をするための単なる 砂糖であることを良く理解したことでしょう。 これらの砂糖の使用はいくらかのオーバーヘッド(通常、FETCH/STORE 操作 当たり二つから四つの余分なオペコード、それに加えてメソッドを 起動するために必要なすべての揮発性変数の生成)を招きます。 このオーバーヘッドは TIE メソッド自身がしっかりしたものであれば、ほぼ 同等なくらい小さなものでしかありませんが、ほんの少し文が長いだけでも オーバーヘッドは無視できないものになります。

変更をローカル化する

Perl には非常に便利な構造があります。

  {
    local $var = 2;
    ...
  }

この構造は以下のものと ほぼ 同じです

  {
    my $oldvar = $var;
    $var = 2;
    ...
    $var = $oldvar;
  }

両者の最も大きな違いは、最初のものが gotoreturndie/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 の値をリストアします。 sSV* に対する型変換をできるポインタでなければなりません; pchar* への型変換が可能であるべきものです。

SAVEFREESV(SV *sv)

擬似ブロック の終端において sv の参照カウントはデクリメントされます。 これは、遅延した SvREFCNT_dec を行うための機構という意味で sv_2motral に似たものです。 しかし、sv_2mortalsv の生存時間を次の文の始めまで延ばす一方、 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 が呼び出されます; この関数 fp のみを引数に取ります。

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)

複数の引数を長さ maxargSV* の配列 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 と引数スタック

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)))
    /* Although the last example is better written as the more
     * efficient: */
    PUSHs(newSVpvs_flags("Some String", SVs_TEMP))

これで、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" を参照してください。

より詳しい情報は、perlxsperlxstut を参照してください。

XSUB でのオートロード

AUTOLOAD ルーチンが XSUB の場合、Perl サブルーチンと同様に、Perl は XSUB の パッケージの $AUTOLOAD 変数にオートロードされたサブルーチンの完全修飾名を 設定します。

しかし、XSUB 自身の特定のフィールドにも同じ情報が設定されます:

    HV *stash           = CvSTASH(cv);
    const char *subname = SvPVX(cv);
    STRLEN name_length  = SvCUR(cv); /* in bytes */
    U32 is_utf8         = SvUTF8(cv);

SvPVX(cv) には、パッケージを含まないサブルーチン名自身が入ります。 UNIVERSAL やそのスーパークラスの AUTOLOAD ルーチンでは、CvSTASH(cv) は 存在しないパッケージのメソッド呼び出しの間は NULL を返します。

注意: $AUTOLOAD への設定は、XS AUTOLOAD サブルーチンに全く 対応していなかった 5.6.1 で動作しなくなりました。 Perl 5.8.0 で XSUB 自身のフィールドの使用を導入しました。 Perl 5.16.0 で $AUTOLOAD への設定が復旧されました。 5.8-5.14 に対応する必要がある場合、XSUB のフィールドを使用してください。

C プログラムからの Perl ルーチンの呼び出し

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 番目の引数 numbertype は、指定された構造体を どれだけ割り付けるのかを指定します。 引数 typesizeof に渡されます。 Newxcに対する最後の引数 castは、引数 pointer が 引数 type と異なるときに使うべきものです。

NewxNewxc とは異なり、Newxz は割り付けたメモリのすべてを ゼロで埋めるために memzero を呼び出します。

再割り当て

    Renew(pointer, number, type);
    Renewc(pointer, number, type, cast);
    Safefree(pointer)

上記の三つのマクロは、メモリのバッファーサイズを変更したりもう 使わなくなったメモリ領域を解放するために使われます。 RenewRenewc の引数は、"魔法のクッキー" 引数が必要ないと いうことを除きそれぞれ NewNewc に一致します。

移動

    Move(source, dest, number, type);
    Copy(source, dest, number, type);
    Zero(dest, number, type);

この三つのマクロは、それぞれ割り付けたメモリ領域に対する移動、 複写、ゼロで埋めるといったことに使われます。 sourcedest という引数は、転送元と転送先の開始番地へのポインタです。 Perl は、構造体 type の大きさ (sizeof 関数を使います)のインスタンスの number 個分だけ、移動、複写、ゼロ埋めを行います。

PerlIO

最新リリースの Perl の開発では、Perl の「通常の」標準入出力ライブラリに 依存している部分を取り除くことと、Perl で別の標準入出力の実装が 使えるようにすることが試みられました。 これにより必然的に、Perl と共にコンパイルされた標準入出力の実装を 呼び出すような新しい抽象層が作られました。 すべての XSUB は、今では PerlIO 抽象層の関数を使うべきで、 これまで使っていた標準入出力に関してのすべての仮定はすべきではありません。

PerlIO 抽象化に関する詳しい記述は perlapio を参照してください。

C での値を Perl スタックに入れる

たくさんのオペコード(これは内部的な 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 が必要でしょう。 dTARGETdXSTARG も参照してください。

スクラッチパッド

残っている疑問は、オペコードに対する targets である SV をいつ 生成するのかということでしょう。 その答えは、カレントユニット -- サブルーチンもしくは(サブルーチンの 外側にある文のためのオペコードのための)ファイル -- が コンパイルされたときです。 この間、特別な無名配列が生成されます; これはカレントユニットのための スクラッチパッド (scrachpad) と呼ばれるものです。

スクラッチパッドはカレントユニットのためのレキシカルやオペコードのための target である SV を保持します。 SV があるスクラッチパッドを、SV のフラグを見ることによって 推測することができます: レキシカルでは SVs_PADMY されていて、 target では 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 のようなコンパイラバックエンド モジュールを使うことです。

コンパイルパス1: チェックルーチン

この木構造は、yacc が perl プログラムを読み込んでその構造を解析している 間にコンパイラによって生成されます。 yacc はボトムアップで動作するので、perl によるコンパイルの最初のパスで 行なわれます。

perl 開発者にとって興味深いのは、このパスで行なわれるいくつかの 最適化でしょう。 これは、"check routines" とも呼ばれる最適化です。 ノード名と対応するチェックルーチンとの間の対応は opcode.pl に 記述されています(このファイルを修正した場合には、make regen_headers を 実行することを忘れないでください)。

チェックルーチンは、ノードが実行順序スレッドを除いて完全に 構築されたときに呼び出されます。 この時点では、構築されたノードに対する back-line が存在しないので、 トップレベルノードに対して、新たなノードを生成したりノードを 解放したりすることを含めて、ほとんどの操作を行うことができます。

このチェックルーチンは木に挿入すべきノードを返します(トップレベルの ノードが変更されていなければ、チェックルーチンはその引数を返します)。

規約により、チェックルーチンは ck_* のような名前を持ちます。 これらは通常サブルーチン new*OP (もしくは convert) から 呼び出されます(これらのサブルーチンは perly.y から呼び出されます)。

コンパイルパス1a: 定数の畳み込み

チェックルーチンが呼び出された直後に、返されたノードはコンパイル時実行の ためのチェックが行なわれます。 もしそうであれば(値が定数であると判定された)、そのノードは即座に実行されて、 「戻り値」に対応する部分木は 定数 ノードで置換され、部分木が削除されます。

定数の畳み込み(constant folding)が働かなければ、実行順序スレッドが 生成されます。

コンパイルパス2: コンテキスト伝播

解析木の一部分のコンテキストがわかっているとき、それは木の末端へ伝播します。 このとき、コンテキストは(実行時コンテキストの二種類ではなく) 無効、真偽値、スカラ、リスト、左辺値の五種類の値を持つことができます。 パス 1 とは対照的に、このパスではトップから末端へと処理が進みます: あるノードのコンテキストは、その下にある部分のコンテキストを決定します。

コンテキストに依存した最適化はこのときに行なわれます。 この動作では解析木が("スレッド" ポインタを通じて)後方参照を含んでいるので、 ノードをこの時に free() することはできません。 このステージでノードを最適化するのを許すために、対象となるノードは free() されるかわりに null() されます(つまり、そのノードの型が OP_NULL に 変えられるということ)。

コンパイルパス 3: 覗き穴最適化

サブルーチン(もしくは eval かファイル)に対する解析木が生成された後で、 そのコードに対する追加パスが実行されます。 このパスはトップダウンでもボトムアップでもなく、(条件に対する複雑さを伴った) 実行順序です。 このステージで行なわれる最適化はパス 2 でのものと同じ制限に従います。

大域変数 PL_peepp で示されている関数を呼び出すことによって、覗き穴最適化が 行われます。 デフォルトでは、PL_peepp は単に大域変数 PL_rpeepp で示されている 関数を呼び出します。 デフォルトでは、これは実行順 op チェーンに対する基本的な op の修正と最適化を 行い、また(条件文の結果の) op のチェーンの両側に対して再帰的に PL_rpeepp を 呼び出します。 エクステンションは、以下のように、サブルーチン毎か再帰ステージのどちらかに フックすることでさらなる最適化や修正を提供できます:

    static peep_t prev_peepp;
    static void my_peep(pTHX_ OP *o)
    {
        /* custom per-subroutine optimisation goes here */
        prev_peepp(o);
        /* custom per-subroutine optimisation may also go here */
    }
    BOOT:
        prev_peepp = PL_peepp;
        PL_peepp = my_peep;

    static peep_t prev_rpeepp;
    static void my_rpeep(pTHX_ OP *o)
    {
        OP *orig_o = o;
        for(; o; o = o->op_next) {
            /* custom per-op optimisation goes here */
        }
        prev_rpeepp(orig_o);
    }
    BOOT:
        prev_rpeepp = PL_rpeepp;
        PL_rpeepp = my_rpeep;

プラガブルな runops

コンパイル木は runops 関数で実行されます。 run.cdump.c に二つの関数があります。 Perl_runops_debug は DEBUGGING で使われ、Perl_runops_standard は その他で使われます。 コンパイル木の実行を細かく制御するために、独自の runops 関数を 設定できます。

既にある runops 関数の一つをコピーして、必要性に合わせて変更するのが おそらく最良です。 それから、XS ファイルの BOOT セクションに、以下の行を追加します:

  PL_runops = my_runops;

この関数はプログラムを出来るだけ早く実行し続けられるように、出来るだけ 効率的にするべきです。

コンパイル時スコープフック

perl 5.14 から、Perl_blockhook_register を使って、コンパイル時 レキシカルスコープ機構にフックすることができるようになりました。 これは次のようにして使います:

    STATIC void my_start_hook(pTHX_ int full);
    STATIC BHK my_hooks;

    BOOT:
        BhkENTRY_set(&my_hooks, bhk_start, my_start_hook);
        Perl_blockhook_register(aTHX_ &my_hooks);

これは、レキシカルスコープのコンパイルを開始する毎に my_start_hook が 呼び出されるように設定します。 利用可能なフックは:

void bhk_start(pTHX_ int full)

これは新しいレキシカルスコープの開始の直後に呼び出されます。 次のような Perl コードは

    if ($x) { ... }

二つのスコープを作ることに注意してください: 一つ目は ( の場所で full == 1 を持って始まり、二つ目は { の場所で full == 0 を持って 始まります。 両方の末尾は } なので、startpre/post_end の呼び出しは 一致します。 このフックで保存スタックにプッシュされたあらゆるものはスコープが終わる直前 (実際には pre_post_end のフックの間) にポップされます。

void bhk_pre_end(pTHX_ OP **o)

これはレキシカルスコープの終わり、スタックを巻き戻す直前に呼び出されます。 o はスコープを表現する op 木のルートです; これはダブルポインタなので 必要なら OP を入れ替えることができます。

void bhk_post_end(pTHX_ OP **o)

これはレキシカルスコープの終わり、スタックを巻き戻した直後に呼び出されます。 o は上述の通りです。 保存スタック上に文字列 eval を呼び出すものがあった場合、pre_post_end がネストして呼び出される可能性があることに注意してください。

void bhk_eval(pTHX_ OP *const o)

これは eval STRING, do FILE, require, use のコンパイルを始める 直前、eval が設定された後に呼び出されます。 o は eval を要求した OP で、通常は OP_ENTEREVAL, OP_DOFILE, OP_REQUIRE のいずれかです。

フック関数を持つと、それを入れる BHK 構造体が必要です。 これは静的に割り当てるのが最良です; 一度登録すると解放する方法はないからです。 関数ポインタは BhkENTRY_set マクロを使ってこの構造体に挿入されます; これはまたどのエントリが有効化を示すフラグを設定します。 何らかの理由で BHK を動的に割り当てる必要がある場合、開始前にゼロで 埋めておく必要があります。

フックが一旦登録されると、無効にするための機構はないので、それが必要な 場合は自分自身でそうする必要があります。 %^H のエントリはおそらく最良の方法です; 効果はレキシカルスコープを 持つからです; しかし一時的にエントリを有効または無効にするために BhkDISABLEBhkENABLE マクロを使うことも可能です。 また、一般的に言ってエクステンションが読み込まれる前に最低一つのスコープが 開いているので、対になる start のない pre/post_end の組を見ることにも 注意するべきです。

内部データ構造を 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_IMPLICIT_CONTEXT

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 に何が起こるの?

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.hglobvar.sym を参照)が関数内でアクセスされて、 dVAR が使われない(dTHX は、必要なら dVAR をインクルードします)場合、 dVAR 定義が必要です。 dVAR の必要性はコンパイル時の定義でのみ気付きます; なぜならさもなければ Perl グローバル変数はそのまま見えるからです。

複数のスレッドから perl を呼び出すのに何か特別なことをするべき?

あるスレッドでインタプリタを作成して、それから他のスレッドでそれを 呼び出そうとするなら、perl の独自のスレッドローカルストレージ (Thread Local Storage (TLS)) スロットがそれぞれのスレッドで正しく 初期化されるようにする必要があります。

perl_allocperl_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_SYS

PERL_IMPLICIT_CONTEXT が、インタプリタが自分自身および渡されたものに関して 知っていること全てをまとめる方法を提供しているのとちょうど同じように、 インタプリタが自分が実行している環境について知っている全てを まとられるようにする計画があります。 これは PERL_IMPLICIT_SYS マクロで有効にされます。 現在のところ、これは Windows で USE_ITHREADS 付きの場合にのみ動作します。

これにより、全てのシステムコールのための(「ホスト」環境と呼ばれる) 追加のポインタを提供する能力を持つようになります。 これにより、独自の状態を保守する全てのシステムの機能について、七つの C 構造体に分解することが可能になります。 デフォルトの perl 実行ファイルのために、通常のシステムコールへの 薄いラッパです (win32/perllib.c を参照してください) が、 (fork() エミュレーションを行うような)より意欲的なホストのために、 異なるインタプリタが実際には異なる「プロセス」であることを装うために 必要になる全ての作業は、ここで行われます。

Perl エンジン/インタプリタとホストは直交する概念です。 一つのプロセスに複数のインタプリタがあることもありますし、複数の「ホスト」が 互いに自由に関連しながらあることもあります。

内部関数

外部の世界に曝されている Perl の内部関数の全ては Perl_ の接頭辞が ついているので、XS 関数や Perl が組み込まれている関数で使われている関数と 衝突しません。 同様に、全てのグローバル変数は PL_ で始まります。 (慣例的に、静的関数は S_ で始まります。)

(PERL_CORE が定義されている) Perl コアの内側では、embed.h にある たくさんの define のおかげで、Perl_ 接頭辞ありとなしのどちらかの関数を 使えます。 エクステンションコードは PERL_CORE を設定するべきでは ありません; これは完全な perl 内部を暴露して、新しい perl のリリース毎に XS を 壊す原因となります。

ファイル embed.h embed.plembed.fnc から自動的に生成されます。 embed.pl は内部関数のためのヘッダファイルのプロトタイプも作成し、 その他の多くの欠片の文書も生成します。 新しい関数をコアに追加したり既にあるものを変更したりした場合、 embed.fnc にある表のデータも変更することが重要です。 以下はその表のエントリの例です:

    Apd |SV**   |av_fetch   |AV* ar|I32 key|I32 lval

2 番目の列は返り値型で、3 番目の列は名前です。 それ以降の列は引数です。 最初の列はフラグの集合です:

A

この関数は公式 API の一部です。 このような関数全ては 'd' も持っているべきですが、ごく一部は違います。

p

この関数は Perl_ 接頭辞を持っています; つまり、Perl_av_fetch として 定義されています。

d

この関数は、すぐに見られる apidoc 機能を使った文書があります。 一部の関数は 'd' ですが 'A' ではありません; 文書はよいものです。

その他の利用可能なフラグは:

s

これは静的関数で、STATIC S_whatever として定義されており、普通は ソース中で whatever(...) として呼び出されます。

n

これはインタプリタのコンテキストを必要としないので、定義には pTHX はなく、 呼び出し元は aTHX を使いません。 ("Background and PERL_IMPLICIT_CONTEXT" を参照してください。)

r

この関数は返りません; croak, exit のようなものです。

f

この関数は printf 形式の可変長の引数を取ります。 引数のリストは以下のように ... で終わります:

    Afprd   |void   |croak          |const char* pat|...
M

この関数は実験的開発 API の一部で、注意なしに変更されたり消滅したり するかもしれません。

o

この関数は、Perl_parse から parse のような定義されている互換性マクロを 持っていません。 これは Perl_parse として呼び出されなければなりません。

x

この関数は Perl コアの外側へエクスポートされません。

m

これはマクロとして実装されています。

X

この関数は明示的にエクスポートされます。

E

この関数は Perl コアに含まれるエクステンションから見えます。

b

バイナリ後方互換性; この関数はマクロですが、(エクスポートされている) Perl_ 実装もあります。

others

その他については embed.fnc の先頭のコメントを参照してください。

embed.pl または embed.fnc を編集した場合、embed.h およびその他の 自動生成ファイルを強制的にリビルドするために make regen_headers を 実行する必要があります。

IV, UV, NV のフォーマットされた表示

IV, UV, NVS を、stdio(3) 形式の %d, %ld, %f のような フォーマッティングコードではなく表示したいなら、互換性のために以下の マクロを使うべきです

        IVdf            IV を 10 進で
        UVuf            UV を 10 進で
        UVof            UV を 8 進で
        UVxf            UV を 16 進で
        NVef            NV を %e 風に
        NVff            NV を %f 風に
        NVgf            NV を %g 風に

これらは 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 を参照してください。

Unicode 対応

Perl 5.6.0 から Unicode 対応が導入されました。 porters と XS 作者にとって、この対応を理解して、書いたコードが Unicode データを壊さないようにすることは重要です。

ところで、Unicode って ?

古く、あまり啓蒙されていなかった時代、私たち全ては ASCII を使っていました。 とりあえず、私たちのほとんどはそうでした。 ASCII の大きな問題は、これは英語だったことです。 えっと、これは本当の問題ではありません; 問題は、英文字を使わない 人々にとっては特に有用ではないということです。 起こったことは、ある種の言語は独自のアルファベットを並びの上半分、 128 から 255 にくっつけるということでした。 もちろん、結局完全に ASCII ではないものの変種だらけになり、標準となるものは 失われました。

さらに悪いことに、数百または数千の文字がある中国語や日本語のような言語を 使うとき、これらを単に 256 に納めるのは不可能なので、ASCII を完全に 忘れてしまって、一つの文字を参照するのに二つの数の組み合わせを使う 独自のシステムを構築しました。

これを修正するために、一部の人々は Unicode, Inc. を作り、考えられる全ての 文字以上のものを含む新しい文字集合を作成しました。 これらの文字を表現するにはいくつかの方法があり、Perl が使うものは UTF-8 と呼ばれます。 UTF-8 は 1 文字を表現するのに可変の数のバイトを使います。 Unicode と Perl の Unicode モデルについては、perlunicode で学べます。

UTF-8 文字列を認識するには?

出来ません。 これは、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 は Unicode 文字を表現するの?

上述したように、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;
    U8 *utf_end; /* 1 beyond buffer pointed to by utf */
    UV uv;      /* Note: a UV, not a U8, not a char */
    STRLEN len; /* length of character in bytes */

    if (!UTF8_IS_INVARIANT(*utf))
        /* Must treat this as UTF-8 */
        uv = utf8_to_uvchr_buf(utf, utf_end, &len);
    else
        /* OK to treat this character as a byte */
        uv = *utf;

この例では、文字の値を得るために utf8_to_uvchr_buf を使うところも見られます; 逆関数 uvchr_to_utf8 は、UV を UTF-8 にするのに使えます:

    if (!UTF8_IS_INVARIANT(uv))
        /* Must treat this as UTF8 */
        utf8 = uvchr_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 は UTF-8 文字列を保管するの?

現在のところ、Perl は Unicode 文字列と非 Unicode 文字列を少し違う形で扱います。 SV のフラグ SVf_UTF8 は、文字列が内部で UTF-8 で エンコードされていることを示します。 これがない場合は、バイトの値が符号位置で、逆も成り立ちます (言い換えると、 文字列は iso-8859-1 としてエンコードされますが、iso-8859-1 の意味論を 使うには use feature 'unicode_strings' が必要です)。 以下のマクロでこのフラグのチェックと操作ができます:

    SvUTF8(sv)
    SvUTF8_on(sv)
    SvUTF8_off(sv)

このフラグは、Perl の文字列の扱いに重要な効果があります: Unicode データが 適切に識別されないと、正規表現、lengthsubstr およびその他の 文字列操作演算子が想定外の結果となります。

問題は、例えば、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 に変換するの?

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 を超える文字が含まれていると失敗します。

他に知っておくべきことは?

実際にはありません。 単に以下のことを覚えておいてください:

カスタム演算子

カスタム演算子対応は独自の 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 はどのカスタム op を扱うかを決定するのに o->op_ppaddr の値を使います。 Perl は、どのカスタム op を扱うのかを決定するために o->op_ppaddr を 使います。 使用する ppaddr 毎に XOP 構造体を作成し、カスタム op のプロパティに XopENTRY_set を設定し、Perl_custom_op_register を使って構造体の ppaddr を 登録するべきです。 典型的な例は次のようなものです:

    static XOP my_xop;
    static OP *my_pp(pTHX);

    BOOT:
        XopENTRY_set(&my_xop, xop_name, "myxop");
        XopENTRY_set(&my_xop, xop_desc, "Useless custom op");
        Perl_custom_op_register(aTHX_ my_pp, &my_xop);

この構造体で利用可能なフィールドは:

xop_name

op のための短い名前です。 これは一部のエラーメッセージに含まれ、また B モジュールによって $op->name として返されるので、B::Concise のような モジュールの出力として現れます。

xop_desc

この op の関数の短い説明。0l

xop_class

この op が様々な *OP 構造体のどれを使うか。 これは op.hOA_* 定数のいずれかです; つまり

OA_BASEOP
OA_UNOP
OA_BINOP
OA_LOGOP
OA_LISTOP
OA_PMOP
OA_SVOP
OA_PADOP
OA_PVOP_OR_SVOP

これは 'PVOP' のみとして解釈されるべきです。 なぜなら _OR_SVOP はコアの PVOP のみで、OP_TRANS は時々代わりに SVOP になります。

OA_LOOP
OA_COP

その他の OA_* 定数は使われるべきではありません。

xop_peep

このメンバは Perl_cpeep_t 型で、 void (*Perl_cpeep_t)(aTHX_ OP *o, OP *oldop) に展開されます。 これが設定されていると、この型の op が覗き穴最適化器に遭遇したときに この関数が Perl_rpeep から呼び出されます。 o は最適化が必要な OP です; oldop は最適化された以前の OP で、これの op_nexto を指しています。

B::Generate では名前によるカスタム op の作成に直接対応しています。

AUTHORS

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 から多くの助けと示唆を受けました。

SEE ALSO

perlapi, perlintern, perlxs, perlembed