Nick Ing-Simmons wrote: >Steve Hay <[EMAIL PROTECTED]> writes: > > >>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 ;-) > [...]
>>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 ;-) > An excellent idea. So attached is hopefully my final take. Using sv_magic(), I've dropped the re-use of the SV in the 2nd arg since (a) I couldn't pull that trick if I actually wanted to use mg_obj for something else and (b) the subsequent mg_find() call is always _immediately_ after sv_magic() anyway so no other magic could have been added. the MAGIC * is then stored within the struct itself. Later on (and possibly in another part of the code, when mg_find() wouldn't be "safe"), the pointer stored with the struct is used to verify that the correct MAGIC * was found. Using sv_magicext() is even easier since it returns the MAGIC * for us. Thanks (once again!) for your help. - 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 { MAGIC *mg; char *buf; } Foo; static Foo *FooAlloc(pTHX); static void FooFree(pTHX_ Foo *foo); static int MagicFooFree(pTHX_ SV *sv, MAGIC *mg); static MGVTBL Foo_vtbl = { NULL, NULL, NULL, NULL, MagicFooFree }; static Foo *FooAlloc(pTHX) { Foo *foo; Newz(0, foo, 1, Foo); Newz(0, foo->buf, 1024, char); strcpy(foo->buf, "Hello, world."); return foo; } static void FooFree(pTHX_ Foo *foo) { Safefree(foo->buf); Safefree(foo); } static int MagicFooFree(pTHX_ SV *sv, MAGIC *mg) { FooFree(aTHX_ (Foo *)mg->mg_ptr); return 1; } MODULE = Foo PACKAGE = Foo void magicfoo() PPCODE: { SV *sv; Foo *foo; MAGIC *mg; // Initialise foo = FooAlloc(aTHX); sv = NEWSV(0, 0); sv_magic(sv, NULL, PERL_MAGIC_ext, (char *)foo, 0); // This mg_find() can't fail since we're doing it straight away. if (!(mg = mg_find(sv, PERL_MAGIC_ext))) croak("Can't find new magic"); foo->mg = mg; mg->mg_virtual = &Foo_vtbl; SvREADONLY_on(sv); // Use it. This could be much later in another function, so we // need to check that mg_find() found the right magic. if (!(mg = mg_find(sv, PERL_MAGIC_ext))) croak("Can't find magic"); if (!(foo = (Foo *)(mg->mg_ptr))) croak("Can't find magic pointer"); if (foo->mg != mg) croak("Found wrong magic pointer"); //printf("%s\n", foo->buf); // Clean up SvREFCNT_dec(sv); } void magicextfoo() PPCODE: { SV *sv; Foo *foo; MAGIC *mg; // Initialise foo = FooAlloc(aTHX); sv = NEWSV(0, 0); if (!(mg = sv_magicext(sv, NULL, PERL_MAGIC_ext, &Foo_vtbl, (char *)foo, 0))) croak("Can't add magic"); foo->mg = mg; SvREADONLY_on(sv); // Use it. This could be much later in another function, so we // need to check that mg_find() found the right magic. if (!(mg = mg_find(sv, PERL_MAGIC_ext))) croak("Can't find magic"); if (!(foo = (Foo *)(mg->mg_ptr))) croak("Can't find magic pointer"); if (foo->mg != mg) croak("Found wrong magic pointer"); //printf("%s\n", foo->buf); // Clean up SvREFCNT_dec(sv); }