On 26/09/02 17:53 +0100, Mark Fowler wrote:
> Okay, I'm getting myself in a twist with inline, and I wondered if you lot
> could help.
>
> I have some accessor methods in my Inline class that take things in like
> so (as based on the Solider example) :
>
> void set_foo(SV* obj, char* string)
>
> and stores the pointer to the string in the struct. Now, since I
> don't know any XS, and my C is pretty rusty, here's my question: What's
> that actually a pointer to?
The first place to look is in the typemap file (lib/ExtUtils/typemap).
For 'char*' it contains:
T_PV
$var = ($type)SvPV_nolen($arg)
$var - string
$type - char*
$arg - ST(1)
ST(1) is just the second argument on the call stack. Remember, everything is
passed to an Inline function as a stack of SV*s. Under the hood, (which you
can check in your .c file) XS generated this from the typemaps:
SV * obj = ST(0);
char * string = (char *)SvPV_nolen(ST(1));
Now we need to know what SvPV_nolen does. Says perlapi:
Returns a pointer to the string in the SV, or a stringified form of
the SV if the SV does not contain a string.
Looks like it returns the raw pointer. But we can't be sure from the doc.
It's a little vague to me. Let's go back to the source. From sv.h:
#define SvPV_nolen(sv) \
((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \
? SvPVX(sv) : sv_2pv_nolen(sv))
OK, so if it's SVf_POK (a string) then call SvPVX:
#define SvPVX(sv) ((XPV*) SvANY(sv))->xpv_pv
If we continue on this train we find that it is definitely just the pointer
from the SV.
> Is it a pointer directly to the same thing
> the PV of the SV points to?...and if so when the SV goes away (though
> garbage collection,) is it entirely possible that that string will that
> string points to will vanish and hence I'll be left with a pointer in my
> struct pointing instead to some random chunk of memory?
So yes. You have a problem. You either need to dup the string, or perhaps
increment the reference count of the original SV. If you choose the latter,
then you'll need to store the SV* in your object, so that you can decrement
the refcount when DESTROY gets called. Of course, you can't use the same
setter function as above. It'll become something like:
void set_foo(SV* obj, SV* string_SV)
> Or have I just lost the ability to program C, and am I barking up the
> wrong ally.
It's all very simple stuff really. Don't let it overwhelm you. I solved this
by simply looking at the generated .c file from Inline, and grepping the Perl
source tree for the relative bits.
Cheers, Brian