Steve Hay <[EMAIL PROTECTED]> writes: >>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 *. >> >It's certainly much easier, but I want this to work from 5.6.0 onwards;
Ok then. >sv_magicext() was added in 5.7.3, I know, I added it ;-) >so I still need to use sv_magic(), at >least for the older Perls. > >And it's only easier w.r.t. adding new magic, isn't it? Yes. >It doesn't help >when you come to retrieve the MAGIC * later to actually use it. True. > >> >>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. >> >Revised version (attached) now passes the SV itself again. Then I can >check that mg->mg_obj == sv after using mg_find() to see if I've found >the right MAGIC *. Am I kidding myself here, or does that work OK? It will work, but adding SV as mg_obj is quite common. Only 100% fool proof scheme I can think of is to store the MAGIC * back into "your struct" - but then you don't need to use mg_find anyway ;-) >Is >it necessary anyway in cases such as this where I've only just created >the SV. That is almost certainly safe if you add the magic right away. >Surely nobody else could have assigned any other magic to it, >so how could it find the wrong magic anyway? Also MAGIC * is a linked list for mg_find() will return most recently added MAGIC * of that 'how' - which is likely yours. We only go on about finding correct MAGIC * as "we" have been burned by obscure bugs when magic is used by multiple XS modules. (e.g. Tk does -varabiable on $foo, and $foo is tie-d to something and is also "tainted", and has UTF-8 char position cache, and ...) > >I've also followed some examples I found in Perl/Tk's objGlue.c and >tkGlue.c and Perl's perlio.c, and called SvRMAGICAL_off(sv) before >finding the magic and assigning the vtbl and then called mg_magical(sv) >afterwards. What is the purpose of turning the magic status off and >then back on again, and do I need to do it? With sv_magic() and PERL_MAGIC_ext you need that trick if you have get/set. sv_magic calls mg_magical() which sets Sv?MAGICAL flags based on entries in the vtable. As sv_magic() doesn't set a vtable for PERL_MAGIC_ext it gets them wrong if a vtable is going to be set. Hence the invention of sv_magicext() so that vtable _IS_ valid at time flags are set. >Indeed, is it safe to do >it, given that SvRMAGICAL_off() isn't documented in perlapi and there >doesn't appear to be any other way of doing it? Major modules like Tk and DBI do what they do. perl5.x is unlikely to change in a way that breaks them. Perl6 (and possibly ponie) is another whole crate of cans-of-worms... >>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. >> >Sounds like a neat idea. > >Perlguts says that a malloc()'ed copy of name is stored in mg_ptr if >namelen >= 0 [sic]. It seems to work OK (and doesn't leak) with namelen >== 0, though, so I guess perlguts is wrong there. So long as you only access 0 chars it doesn't matter than the pointer is invalid ;-) >Looking at sv.c, >Perl_sv_magic() doesn't touch name/namelen -- it delegates the handling >of that to Perl_sv_magicext() which behaves exactly as you say. And sv_magicext() was created by a cut/paste from perl5.6-ish sv_magic(). So the logic hasn't changed. The current code base has grown a bit of code _after_ call to sv_magicext() which worries me slightly. >> >Not sure I like that since behaviour when namelen < 0 isn't documented. >So I've added an I32 signature member to my struct and check that it has >the correct value after retrieving the magic when it is being used later. If you use the MAGIC * as the "signature" it can't fail ;-)