Steve Hay <[EMAIL PROTECTED]> writes: >Nick Ing-Simmons wrote: > >The magic version is new to me. Have I done it right?
Looks okay after a quick skim. >I've never used >magic before, and had a couple of questions about it: > >- What is the second arg to sv_magic() for? Would there be any merit in >storing the Foo struct in there? It would still need to be wrapped in >an SV somehow, though (mg_obj is an SV *), so we're just going round in >circles then. The various args to sv_magic() are not well documented. I always end up going back to source to remind myself what they do. In principle it is "your magic" so you can do what you like with various mg_xxx fields and the args set those fields. Snag is that there are legacy rules that apply in some cases. So looking at Perl_sv_magicext() in sv.c (which is good entry point to use if your perl is new enough to have it and you are adding a vtable), saves the problem of the mg_find() finding someone elses MAGIC *. Second arg becomes mg_obj it is usually REFCNTed when you add the magic and SvREFCNT_dec on unmagic. This can be handy. It is used to hold the "object" behind a 'tie' for example. If mg_obj is SV itself or for certain kinds of 'how' and in some cases for GV * REFCNT is skipped. > >- What were the final two args to sv_magic() for? I just passed (NULL, >0). Perlguts gives an example of using PERL_MAGIC_uvar which passed a >struct in there. Could I have done something similar to avoid having to >find the magic and manually assign mg_virtual? The char * and len can be used (almost) as you see fit. The char * may be the place to save a pointer to the struct. If you do that length should be 0. If length is positive then mg_ptr is a _copy_ of string you pass in. > >- Perlguts also says this: > >"Note that because multiple extensions may be using PERL_MAGIC_ext or >PERL_MAGIC_uvar magic, it is important for extensions to take extra care >to avoid conflict. Typically only using the magic on objects blessed >into the same class as the extension is sufficient. For PERL_MAGIC_ext >magic, it may also be appropriate to add an I32 'signature' at the top >of the private data area and check that." When you are using MAGIC to add a vtable e.g. a free() entry to do cleanup then chacking isn't quite as important (each free is called with the MAGIC * that it is associated with), but beware mg_find() finding wrong MAGIC when you set vtable. But if you are just using PERL_MAGIC_ext to associate data with an SV you must take care that you don't find someone elses data that has been added as well. Another "check" might be to set length to (say) -sizeof(struct) (-ve to avoid take-a-copy of char * as described above). > >What is the "private data area" to which it refers? Your struct. > Does it mean >mg_ptr/mg_len? > >- Steve > > >------------------------------------------------ >Radan Computational Ltd. > >The information contained in this message and any files transmitted with it are >confidential and intended for the addressee(s) only. If you have received this >message in error or there are any problems, please notify the sender immediately. >The unauthorized use, disclosure, copying or alteration of this message is strictly >forbidden. Note that any views or opinions presented in this email are solely those >of the author and do not necessarily represent those of Radan Computational Ltd. The >recipient(s) of this message should check it and any attached files for viruses: >Radan Computational will accept no liability for any damage caused by any virus >transmitted by this email. >#include "EXTERN.h" >#include "perl.h" >#include "XSUB.h" > >#include "ppport.h" > >typedef struct { > char *buf; >} Foo; > >static Foo *FooAlloc(pTHX); >static void FooFree(pTHX_ Foo *foo); >static int MagicFooFree(pTHX_ SV *sv, MAGIC *mg); > >static MGVTBL Foo_vtab = { > NULL, > NULL, > NULL, > NULL, > MagicFooFree >}; > >static Foo *FooAlloc(pTHX) { > Foo *foo; > Newz(0, foo, 1, Foo); > Newz(0, foo->buf, 1024, char); > return foo; >} > >static void FooFree(pTHX_ Foo *foo) { > Safefree(foo->buf); > Safefree(foo); >} > >static int MagicFooFree(pTHX_ SV *sv, MAGIC *mg) { > FooFree(aTHX_ INT2PTR(Foo *, SvUVX(sv))); > return 1; >} > >MODULE = Foo PACKAGE = Foo > >void >manualfoo() >PPCODE: >{ > SV *sv; > Foo *foo; > foo = FooAlloc(aTHX); > sv = newSVuv(PTR2UV(foo)); > SvREADONLY_on(sv); > FooFree(aTHX_ INT2PTR(Foo *, SvUVX(sv))); > SvREFCNT_dec(sv); >} > >void >objectfoo() >PPCODE: >{ > SV *sv, *rv; > HV *stash; > Foo *foo; > foo = FooAlloc(aTHX); > sv = newSVuv(PTR2UV(foo)); > stash = gv_stashpv("Foo", 1); > rv = newRV_noinc(sv); > sv_bless(rv, stash); > SvREADONLY_on(sv); > SvREFCNT_dec(rv); >} > >void >DESTROY(self) >SV *self; >PPCODE: >{ > SV *sv; > sv = SvRV(self); > FooFree(aTHX_ INT2PTR(Foo *, SvUVX(sv))); >} > >void >magicfoo() >PPCODE: >{ > SV *sv; > Foo *foo; > MAGIC *mg; > foo = FooAlloc(aTHX); > sv = newSVuv(PTR2UV(foo)); > sv_magic(sv, NULL, PERL_MAGIC_ext, NULL, 0); > SvREADONLY_on(sv); > mg = mg_find(sv, PERL_MAGIC_ext); > mg->mg_virtual = &Foo_vtab; > SvREFCNT_dec(sv); >}