I played a bit with it...

This is the only thing I can come up with:

What you should be doing instead (I think) is store the thing it refences to in perlobj and increase the counter of that.
That is: use:

sv_setref_pv(perlref, "Artist", (void*)artist); artist->perlobj = SvRV(perlref);
instead of:
artist->perlobj = sv_setref_pv(perlref, "Artist", (void*)artist);

The attached code does that and is (IMHO) a bit easier to understand...

#!/usr/bin/perl -l use strict; use warnings; use Inline C => <<'END_C'; typedef struct Artist { char *name; SV *perlobj; } Artist; typedef struct CD { Artist *artist; /* ... */ } CD; /* Constructor for Artist. */ SV* new_artist(char *name) { SV *perlref; Artist *artist; printf("Creating artist: %s\n", name); /* allocate and initialize Artist struct */ New(0, artist, 1, Artist); artist->name = savepv(name); /* create perl object and ref; store pointer to object in struct * +/ perlref = newSV(0); sv_setref_pv(perlref, "Artist", (void*)artist); artist->perlobj = SvRV(perlref); return perlref; } /* Constructor for CD. */ SV* new_cd(SV *artist_sv) { CD *cd; Artist *artist = (Artist*) SvIV(SvRV(artist_sv)); SV *cd_ref; printf("Creating CD (artist = %s)\n", artist->name); /* allocate and initialize CD struct */ New(0, cd, 1, CD); cd->artist = artist; SvREFCNT_inc(artist->perlobj); cd_ref = newSV(0); sv_setref_pv(cd_ref, "CD", (void*)cd); return cd_ref; } /* getter */ SV* get_name_from_artist(SV *artist_sv) { Artist *artist = INT2PTR( Artist*, SvIV(SvRV(artist_sv)) ); return newSVpv(artist->name, 0); } /* getter */ SV* get_artist_name_from_cd(SV *cd_sv) { CD *cd = INT2PTR( CD*, SvIV(SvRV(cd_sv)) ); return newSVpv(cd->artist->name, 0); } /* Destructor for Artist objects */ void destroy_artist(SV *artist_sv) { Artist *artist = INT2PTR( Artist*, SvIV(SvRV(artist_sv)) ); Safefree(artist->name); Safefree(artist); } /* Destructor for CD objects */ void destroy_cd(SV *cd_sv) { CD *cd = INT2PTR( CD*, SvIV(SvRV(cd_sv)) ); SvREFCNT_dec(cd->artist->perlobj); Safefree(cd); } SV* refcnt (SV *sv) { return newSViv(SvREFCNT(sv)); } END_C package Artist; use strict; use warnings; use Devel::Peek qw( Dump ); sub DESTROY { my $artist = shift; my $artist_name = main::get_name_from_artist($artist); print STDERR "Artist::DESTROY called ($artist_name)"; main::destroy_artist($artist); } package CD; use strict; use warnings; sub DESTROY { my $cd = shift; print STDERR "CD::DESTROY called."; main::destroy_cd($cd); } package main; use strict; use warnings; { # Create an Artist object. my $artist = new_artist("Johnny Houseburner"); print 'Refcount: $artist: ' . refcnt($artist); print 'Refcount: $$artist: ' . refcnt($$artist); # Save a copy of the Artist object in a CD object. my $cd = new_cd($artist); print 'Refcount: $artist: ' . refcnt($artist); print 'Refcount: $$artist: ' . refcnt($$artist); print 'Refcount: $cd: ' . refcnt($cd); print 'Refcount: $$cd: ' . refcnt($$cd); print 'undef $artist'; undef $artist; print "Artist name via cd: " . get_artist_name_from_cd($cd); print 'undef $cd'; undef $cd; print "End block"; } print "End code";

The output of the code:

Creating artist: Johnny Houseburner Refcount: $artist: 1 Refcount: $$artist: 1 Creating CD (artist = Johnny Houseburner) Refcount: $artist: 1 Refcount: $$artist: 2 Refcount: $cd: 1 Refcount: $$cd: 1 undef $artist Artist name via cd: Johnny Houseburner undef $cd CD::DESTROY called. Artist::DESTROY called (Johnny Houseburner) End block End code

(Small note: this code is still easy to segfault: all you need to do is change $$artist.)


In reply to Re^2: XS: Manipulating refcounts by Animator
in thread XS: Manipulating refcounts by creamygoodness

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.