• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Introduction to Perl MAGIC
 

Introduction to Perl MAGIC

on

  • 2,916 views

Used for talks in YAPC::Asia 2009

Used for talks in YAPC::Asia 2009

- gfx

Statistics

Views

Total Views
2,916
Views on SlideShare
2,882
Embed Views
34

Actions

Likes
0
Downloads
5
Comments
0

2 Embeds 34

http://d.hatena.ne.jp 32
http://www.slideshare.net 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Introduction to Perl MAGIC Introduction to Perl MAGIC Presentation Transcript

    • Introduction to Perl MAGIC for XS writers Fuji, Goro (gfx) <gfuji@cpan.org> YAPC::Asia 2009, Sep 10th
      • perlguts says:
        • This section still under construction. Ignore everything here. Post no bills. Everything not permitted is for bidden.
      • perlguts says about &quot;Magic Variable&quot;:
        • Any SV may be magical, that is, it has special features that a normal SV does not have. These features are stored in the SV structure in a linked list of struct magic 's, typedef'ed to MAGIC .
      • MAGIC features:
        • hook methods + managed data
      • /* mg.h of 5.10.1 */
      • struct magic {
      • MAGIC* mg_moremagic;/* pointer to the next magic */
      • MGVTBL* mg_virtual ; /* pointer to magic hook methods */
      • U16 mg_private ; /* user data(1) : small integer */
      • char mg_type; /* type identity, e.g. PERL_MAGIC_ext */
      • U8 mg_flags; /* flags reserved by core */
      • I32 mg_len; /* the length of mg_ptr (or HEf_SVKEY) */
      • SV* mg_obj ; /* user data(2) : sv */
      • char* mg_ptr ; /* user data(3) : managed pointer or sv */
      • };
      • /* perl.h */
      • typedef struct magic MAGIC;
      • /* mg.h of 5.10.1 */
      • #ifdef STRUCT_MGVTBL_DEFINITION
      • STRUCT_MGVTBL_DEFINITION;
      • #else
      • struct mgvtbl {
      • int (CPERLscope(* svt_get )) (pTHX_ SV *sv, MAGIC* mg);
      • int (CPERLscope(* svt_set )) (pTHX_ SV *sv, MAGIC* mg);
      • U32 (CPERLscope(*svt_len)) (pTHX_ SV *sv, MAGIC* mg);
      • int (CPERLscope(*svt_clear)) (pTHX_ SV *sv, MAGIC* mg);
      • int (CPERLscope(* svt_free )) (pTHX_ SV *sv, MAGIC* mg);
      • int (CPERLscope(*svt_copy)) (pTHX_ SV *sv, MAGIC* mg,
      • SV *nsv, const char *name, int namlen);
      • int (CPERLscope(*svt_dup)) (pTHX_ MAGIC *mg, CLONE_PARAMS *param);
      • int (CPERLscope(*svt_local)) (pTHX_ SV *nsv, MAGIC *mg);
      • };
      • #endif
      • # perlguts
      • Function pointer Action taken
      • ---------------- ------------
      • svt_get Do something before the value of the SV is retrieved .
      • svt_set Do something after the SV is assigned a value.
      • svt_len Report on the SV's length.
      • svt_clear Clear something the SV represents.
      • svt_free Free any extra storage associated with the SV.
      • svt_copy copy tied variable magic to a tied element
      • svt_dup duplicate a magic structure during thread cloning
      • svt_local copy magic to local value during 'local‘
      • (snip)
      • Some special variables are bound to C variables
        • $^H -> PL_hints
        • $! -> errno
      • Weak references
      • Defer elements
      • UTF8 helpers
      • To look into MAGICs, you can use Devel::Peek
        • perl –MDevel::Peek –e ‘Dump $^H;’
      • B::Hooks::EndOfScope via Variable::Magic
        • using hook methods
      • WeakRef::Auto
        • using hook methods
      • Sub::Name
        • using managed data
      • Class::MOP/Moose
        • using managed data
        • under construction!
      • $ perl -MDevel::Peek -e 'Dump @ISA'
      • SV = RV(0x8ce3174) at 0x8ce3168
      • REFCNT = 1
      • FLAGS = (TEMP,ROK)
      • RV = 0x8cf33c0
      • SV = PVAV(0x8ce4038) at 0x8cf33c0
      • REFCNT = 2
      • FLAGS = (SMG,RMG) # has SetMagic and GetMagic
      • MAGIC = 0x8cf62c8
      • MG_VIRTUAL = &PL_vtbl_isa # mg_virtual
      • MG_TYPE = PERL_MAGIC_isa(I) # mg_type
      • MG_OBJ = 0x8ce3208 # mg_obj
      • ARRAY = 0x0
      • FILL = -1
      • MAX = -1
      • ARYLEN = 0x0
      • FLAGS = (REAL)
      • # @ISA magic will invalidate methods caches when class hierarchies are changed.
      • If you don’t write XS, you need not to care about MAGIC, but otherwise you must care about it because Perl APIs do not always handle MAGIC.
      • Perl レベルでは MAGIC を意識する必要はないが, C レベルでは MAGIC を扱う API と扱わない API が区別されているので, XS を書くならば常に意識しなければならない。
    • MAGI C をハンドルする API を知る
      • MAGIC を起動する API
        • SvIV/SvNV/SvPV など -> SetMAGIC
        • sv_setsv_mg などの sv_setx_mg 系 -> GetMAGIC
        • sv_isobject など( perlapi に載っていないことが多い)
      • MAGIC を起動しない API
        • SvIVX/SvOK などSVの要素を直接参照するもの
        • sv_setx 系で _mg の付かないもの
        • xsubpp のデフォルト typemap の いくつか (後述)
    • xsubpp/typemap の特性を知る
      • typemap のうち、 MAGIC を起動しないものがある
        • char*, int などは MAGIC をハンドルする
        • HV*, AV*, CV* などは MAGIC をハンドルしない
      • ドキュメントには書いていないので注意
      • Magic::Example に例
        • http://github.com/gfx/YAPC-Asia-2009-gfx/tree/master
        • ->> perl Makefile.PL && make test (should fail)
    • [ah]v_store の戻り値
      • The return value will be NULL if the operation failed or if the value did not need to be actually stored within the hash (as in the case of tied hashes ) (perlapi)
      • タイハッシュ・配列に store すると、 NULL を返す
        • その場合、 store したSVを解放しなければならない
      • XS内のみで使う hv/av ならば戻り値は無視できる
        • (void)hv_store_ent(hv, key, val, 0U); /* OK */
    • スタック操作を伴うケース
      • Question
        • XPUSHs() などはSPを realloc() する可能性がある
        • newSVsv() などは MAGIC を起動する可能性がある
        • ∴ newSVsv() の前後でSPの値が変わる可能性がある?
      • Answer
        • No. メタスタック (PERL_SI) メカニズムによるSPの保護
        • MAGIC(tie), destructor などで自動的に呼び出されるサブルーチンについては、SPが変わる心配はない
        • ただし、エクステンションが hook methods 内でサブルーチンを呼ぶ場合は、メタスタックの管理が必要
          • PUSHSTACK/POPSTACK (but no document)
    • PERL_MAIGC_ext
      • sv_magicext(sv, mg_obj, PERL_MAGIC_ext, &mg_vritual, mg_ptr, mg_len)
        • mg_ptr は char* で、 mg_len でその長さを指定
          • mg_len が 1 以上のとき、 mg_ptr は sv_magicext 内で malloc され、 sv が解放されるときに free される
          • mg_len が 0 のとき、 mg_ptr はそのまま保存される
          • mg_len が HEf_SVKEY のとき、 mg_ptr は SV* と見なされ、 sv_magicext 内で SvREFCNT_inc され、 sv が解放されるときに SvREFCNT_dec される (mg_obj と同じ扱い )
      • つまり、 mg_obj と mg_ptr+HEf_SVKEY のSVは、 mortalize するか、 sv_magicext のあとに SvREFCNT_dec しなければならない
    • PERL_MAGIC_ext の利用
      • hook methods
        • 挙動が不気味すぎて扱いが難しい
          • Magic::Watch (on github) に例はあるが… :(
        • 注意事項が沢山ありすぎる
      • managed data
        • 時代は XS code templates!
    • XS code templates (1)
      • XSUBを動的に生成するメカニズム
      • クロージャのXS版
      • MAGIC を使って cv にデータを添付する
      • Template (XSUB) + Parameters (MAGIC)
      • Used by
        • Class::XSAccessor
        • Class::MOP/Moose (future version)
    • XS code templates (2)
      • 動的コード生成の方法
        • eval $subroutine_source_code
        • closure (anonymous subroutine)
        • XS code templates
        • Inline::x86 による JIT
      Gen Time Run Time Maintain eval slow moderate hard closure moderate slow easy XSt fast fast hard Inline::x86 fastest fastest hellish
    • Example
      • /* in XS */
      • static MGVTBL xst_id; /* the MAGIC identity */
      • CV* xsub = newXS(name, xs_impl, file);
      • HV* hv = newHV();
      • MAGIC* mg;
      • mg = sv_magic((SV*)xsub, (HV*)hv, PERL_MAGIC_ext, &xst_id, NULL, 0);
      • SvREFCNT_dec(hv);
      • CvXSUBANY(xsub).any_ptr = (void*)hv; /* shortcut */
      • /* ... */
      • XS(xs_impl){
      • dVAR; dXSARGS;
      • HV* hv = (HV*)XSANY.any_ptr ; /* shortcut */
      • /* ... */
      • }
    • That's all
      • Enjoy Perl MAGIC!
      • Thank you for your attention.