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

Reply via email to