Why is it that when I create an SV and assign magic to it in an XSUB, and then return the magical SV to Perl code, I find that the scalar in the Perl code no longer seems to have magic?
The attached sample module has XSUB's to create a magical SV (fooalloc and fooallocext), an XSUB to use the magical SV created (foo) and another to free it (foofree, not strictly necessary since the SV here is mortal anyway). I was intending that when I run perl -Mblib -MFoo -e "$a=Foo::fooalloc();Foo::foo($a);Foo::foofree($a)" it would print "Hello, world.". But it doesn't. It croak()'s in foo() claiming that it can't find the magic on the SV passed in. I've added some sv_dump()'s into the allocators to look at the SV being returned; using Devel::Peek::Dump() in the Perl code I can also look at what it received, and I find that they're completely different: perl -Mblib -MFoo -MDevel::Peek -e "$a=Foo::fooalloc();Dump($a)" outputs this: SV = PVMG(0x1835170) at 0x1820184 REFCNT = 1 FLAGS = (TEMP,RMG) IV = 0 NV = 0 PV = 0 MAGIC = 0x182a188 MG_VIRTUAL = 0x354410 MG_TYPE = PERL_MAGIC_ext(~) MG_PTR = 0x185a738 "" SV = PVMG(0x1835190) at 0x183578c REFCNT = 1 FLAGS = () IV = 0 NV = 0 PV = 0 Where has all the magic gone? - 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) { Foo *foo; if (foo = (Foo *)(mg->mg_ptr)) FooFree(aTHX_ foo); return 1; } MODULE = Foo PACKAGE = Foo void fooalloc() PPCODE: { Foo *foo; SV *sv; MAGIC *mg; foo = FooAlloc(aTHX); sv = sv_newmortal(); sv_magic(sv, NULL, PERL_MAGIC_ext, (char *)foo, 0); if (!(mg = mg_find(sv, PERL_MAGIC_ext))) croak("Can't add magic"); mg->mg_virtual = &Foo_vtbl; foo->mg = mg; sv_dump(sv); EXTEND(SP, 1); PUSHs(sv); XSRETURN(1); } void fooallocext() PPCODE: { Foo *foo; SV *sv; MAGIC *mg; foo = FooAlloc(aTHX); sv = sv_newmortal(); if (!(mg = sv_magicext(sv, NULL, PERL_MAGIC_ext, &Foo_vtbl, (char *)foo, 0))) croak("Can't add magic"); foo->mg = mg; sv_dump(sv); EXTEND(SP, 1); PUSHs(sv); XSRETURN(1); } void foofree(sv) SV *sv; PPCODE: { SvREFCNT_dec(sv); } void foo(sv) SV *sv; PPCODE: { MAGIC *mg; Foo *foo; if (!(mg = mg_find(sv, PERL_MAGIC_ext)) || !(foo = (Foo *)(mg->mg_ptr)) || foo->mg != mg) croak("Can't find our magic"); printf("%s\n", foo->buf); }