休日にまとめてエントリを書くと,全部 Perl が SICP ですね!
どうも,perlxs を読む前に perlguts を読んだ方がいいっぽいので,今日はずっと perlguts を読んでみたいとおもっています.guts てなんだ.
Perl には 3 種類のデータ型が typedef されています.
- SV (Scalar)
- AV (Array)
- HV (Hash)
しかしながら,他にもあって,
- IV (Signed Integer; じつはポインタも持てる?)
- UV (Unsigned Integer)
- I32,I16
- U32,U16 (それぞれ32,16 ビット長以上の(たぶん) Unsigned Integer)
- NV (double)
- PV (String)
とかある.
SV は他のデータ型から作成するとができるみたいです.この他のデータ型からの作成を,perlguts では load と呼んでいるっぽい.
An SV can be created and loaded with one command.
例えば IV から SV* への変換は newSViv( IV ) という関数で行えるみたいです.同様に,UV や double からの関数も用意されてます.SV は上の文章の通り何も無いところから作成するときもできて,それは newSV( len ) で行う.len は記憶領域のバイト数みたい.
SV *sv = newSV(0); /* no storage allocated */ SV *sv = newSV(10); /* 10 (+1) bytes of uninitialised storage allocated */
SV の値を変更するためには,何のデータ型を SV にセットするのかによって呼び出す関数が違う.こうやって,動的型付けが提供されているんだなー.
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* の指す先を変更しているみたい.Shibuya.pm (XS Nite) でもそんなことを聞いた.
じゃぁその SV* が指す SV の値を Get するにはどうすれば! それをやってくれるのが以下のマクロ.
SvIV(SV*) SvUV(SV*) SvNV(SV*) SvPV(SV*, STRLEN len) SvPV_nolen(SV*)
SvPV て返ってくる文字列の長さを len で制御できるみたいなんだけど,長さがなんぼでもいいときは,SvPV_nolen を使うと.なるほど.
あと,こんな呼び出しはやめたほうが良いっぽい.評価順序が微妙なのかな.
foo(SvPV(s, len), len);
SV* の指す先が true なのか false なのかを調べるのは
SvTRUE(SV*)
SV にもっと大きなメモリを自分で割り当てるときは
SvGROW(SV*, STRLEN newlen)
SV の持っているデータ型のチェックは
SvIOK(SV*) SvNOK(SV*) SvPOK(SV*)
を使う.
SV が持っている文字列の長さを Get/Set するのは以下の関数.あれ,これで strlen できるんじゃね?
SvCUR(SV*) SvCUR_set(SV*, I32 val)
SvEnd(SV*)
は文字列の最後をさすポインタを取得する.