Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Inline::C - object accessor failure

by fireartist (Chaplain)
on Oct 26, 2005 at 15:25 UTC ( [id://503092]=perlquestion: print w/replies, xml ) Need Help??

fireartist has asked for the wisdom of the Perl Monks concerning the following question:

I've tried changing some code that used XS to use Inline::C instead.

When I run this code, it dies (with no error message, just a windows error dialog). If I try running it again, it seems to use the compiled code, but prints a symbol character, rather than the expected output.

I think I'm making an error with my perl API calls, but have no idea where I'm going wrong.

(I'm running perl 5.8.7, compiled with mingw/gcc 3.4.2) on winXP.

package InlineTest; use strict; use warnings; use Inline 'C' => <<CEND; SV* x (SV* hashref) { HV* self; SV* x; self = (HV*)SvRV(hashref); x = hv_fetch( self, "x", 1, 0 ); return x; } CEND sub new { my $self = shift; return bless {@_}, $self; } package main; use strict; use warnings; my $t = InlineTest->new( x => 'foo' ); print $t->x;

Replies are listed 'Best First'.
Re: Inline::C - object accessor failure
by samtregar (Abbot) on Oct 26, 2005 at 16:03 UTC
    Check the signature for hv_fetch again. You're assigning it to an SV* but it returns an SV**.


Re: Inline::C - object accessor failure
by BrowserUk (Patriarch) on Oct 26, 2005 at 16:36 UTC

    samtragar has answered the question, but to be able to discover this for yourself, you'll need to add some options to the build process so that the intermediate files are retained and you can inspect them. Something like this is useful:

    use Inline 'NoClean', 'FORCE', 'INFO' ; use Inline Config => WARNINGS => 4; use Inline 'C' => <<CEND, NAME =>'yourname'; ...

    Note: I've also attempted to enable warnings above. It doesn't work, or at least they are not displayed when the program is built. If they were, the C compiler would have warned that you were assigning a SV** to an SV*.

    The only way I have found to get the warning displayed on my system is to deliberately include a fatal error. A line like fred; will give an error

    test.xs(13) : error C2065: 'fred' : undeclared identifier

    And the warnings will also be displayed.

    There has to be a better way, but I haven't found it.

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Inline::C - object accessor failure
by robin (Chaplain) on Oct 26, 2005 at 16:55 UTC

    I haven't used Inline::C very much, so I'm not really familiar with its idiosyncracies. I would have expected this:

    use Inline 'C' => <<CEND; SV* x (HV* self) { SV** x_ref = hv_fetch( self, "x", 1, 0 ); return (x_ref ? *x_ref : &PL_sv_undef); } CEND
    to work, but in fact it causes some nasty internal warnings:
    Attempt to free temp prematurely: SV 0x816f1c4. Attempt to free unreferenced scalar: SV 0x816f1c4.
    You'll only get the warnings if you have a DEBUGGING compile of perl, but they indicate a real problem! I'm not certain, but I would guess this is actually a bug in Inline::C. Update: it's actually a feature of XS – see rest of thread. Thanks sfink!

    It seems that the following works correctly:

    use Inline 'C' => <<CEND; void x (HV* self) { SV** x_ref = hv_fetch( self, "x", 1, 0 ); Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push (x_ref ? *x_ref : &PL_sv_undef); Inline_Stack_Done; } CEND

      Actually, that's XS.

      In your first example, you're returning an SV* you looked up in the hash, so you don't own it. Inline::C works by generating an XS file and running xsubpp, and XS mortalizes any SV* that you return via its RETVAL mechanism. Thus, you've mortalized an SV* owned by the hash. Which is not at all pointed out by the Inline documentation (it should be in Inline::C-Cookbook), and the description in perlxs seems suspicious to me to (it claims that RETVAL is mortalized via the typemap file, but I'm looking at the typemap and I see no relevant mention of 'mortal' anywhere -- nor any mention of RETVAL.)

      So I think this should work:

      And it doesn't seem to leak, either: replace the last two lines with
      sub Whiner::DESTROY { print "Dying!\n" } my $t = InlineTest->new( x => bless [], 'Whiner' ); print $t->x, "\n"; undef $t; print "Done.\n";
      and it prints "Dying!" before "Done."

      In general, I would also recommend using <<'CEND' rather than <<CEND for blocks of Inline code, because if you want to insert a debugging printf("Got here!\n"), then you don't really want that \n to be translated to a newline.

      I work for Reactrix Systems, and am willing to admit it.
        ...XS mortalizes any SV* that you return via its RETVAL mechanism ... and the description in perlxs seems suspicious to me to (it claims that RETVAL is mortalized via the typemap file, but I'm looking at the typemap and I see no relevant mention of 'mortal' anywhere -- nor any mention of RETVAL.)
        Interestingly, RETVAL is mortalized by xsubpp itself (see the generate_output cruft in the xsubpp source) - so it is hardwired into XS... But it usually turns out to do what you want, except for the cases, when it does not.

        Wow, thanks! I've been looking at the 5.8.1 version of perlxs, which doesn't mention the automatic mortalization of RETVAL at all. It looks like that section was added in 5.8.4.

        (Inline was written quite a while before this feature was documented, so maybe ingy didn't know about it and that's why the Inline::C documentation doesn't mention it?)

        You'd think that not knowing about this would have caused me problems by now. The odd thing is, I've just looked over all my XS code and I don't seem to have run afoul of it anywhere. I suppose it helps that I usually use PPCODE instead of CODE.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://503092]
Approved by ww
Front-paged by derby
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (7)
As of 2024-04-16 10:10 GMT
Find Nodes?
    Voting Booth?

    No recent polls found