Dear monks,

I am trying to construct self-referential objects (tree/DAG nodes) using Inline::C. These are the requirements:

I am hampered by the following challenges: Nonetheless, playing around with the Inline::C cookbook and the results of various google searches is getting me started with just enough knowledge to be dangerous. Below is the simplest case I came up with just for child->parent relationships:

#!/usr/bin/perl package Node; use strict; use warnings; use Inline C => <<'__EOI__'; // XXX no children for now typedef struct Node { struct Node* parent; SV* sv; } Node; Node* new(const char * classname) { Node *self; // allocate and initialize struct Newx(self, 1, Node); self->parent = NULL; // create perl object and ref SV* perlref = newSViv((IV)self); SV* obj_ref = newRV_noinc(perlref); sv_bless(obj_ref, gv_stashpv(classname, TRUE)); SvREADONLY_on(perlref); // store pointer to object in struct self->sv = obj_ref; return self; } // should NOT alter refcount Node* set_parent(Node* self, Node* parent) { self->parent = parent; return self; } Node* get_parent(Node* self) { return self->parent; } // XXX get/set children deferred void destroy_node(Node* self) { Safefree(self); } __EOI__ sub DESTROY { my $self = shift; warn "destroying $self"; $self->destroy_node; } package main; use Devel::Peek; $|++; my $node = Node->new; my $parent = Node->new; print "NODE: "; Dump($node); print "---\n"; print "PARENT: "; Dump($parent); print "---\n"; $node->set_parent($parent); print "FROM FIELD: "; print Dump($node->get_parent); print "---\n";

Here is my typemap:

TYPEMAP Node * NODE INPUT NODE $var = ($type)SvIV(SvRV($arg)); OUTPUT NODE $arg = $var->sv;

When I run this, the following output is produced:

NODE: SV = IV(0x7fcc7b8041b8) at 0x7fcc7b8041c8 REFCNT = 1 FLAGS = (PADMY,ROK) RV = 0x7fcc79803e98 SV = PVMG(0x7fcc790023b0) at 0x7fcc79803e98 REFCNT = 1 FLAGS = (OBJECT,IOK,READONLY,pIOK) IV = 140516178002128 NV = 0 PV = 0 STASH = 0x7fcc7a004e70 "Node" --- PARENT: SV = IV(0x7fcc7a008838) at 0x7fcc7a008848 REFCNT = 1 FLAGS = (PADMY,ROK) RV = 0x7fcc79803ce8 SV = PVMG(0x7fcc79002770) at 0x7fcc79803ce8 REFCNT = 1 FLAGS = (OBJECT,IOK,READONLY,pIOK) IV = 140516178002208 NV = 0 PV = 0 STASH = 0x7fcc7a004e70 "Node" --- FROM FIELD: SV = UNKNOWN(0xff) (0x7fcc7a004630) at 0x7fcc79803fd0 REFCNT = 0 FLAGS = (TEMP) Attempt to free unreferenced scalar: SV 0x7fcc79803fd0, Perl interpret +er: 0x7fcc79800000 at ref.pl line 72. --- destroying Node=SCALAR(0x7ff391803ce8) at ref.pl line 51. destroying Node=SCALAR(0x7ff391803e98) at ref.pl line 51.

My conclusions are as follows:

  1. Object instantiation works more or less as I hoped. The typemap conversion gives me back the blessed "obj_ref" from the constructor, which in turn has the reference count from "perlref", which is created from casting the pointer to Node* as an IV integer value. (Correct?).
  2. Method invocation works as hoped. The getters and setters are found, the invocant is converted with the macros SvIV(SvRV()) to get the reference, then its integer value, which we then cast as Node* pointer. (Correct?).
  3. The additional method argument to set_parent is also converted correctly, using the same typemapping as the invocant.
  4. However, getting our parent back results in perl not knowing what to do with the parent Node*. Some sort of unknown, moribund thing comes back. This thing throws up the "Attempt to free unreferenced scalar..." warning. This part I really don't understand and I could use some help/explanation.
  5. Otherwise, the intended destructor for nodes is called as intended. It doesn't give any warnings, but whether that means I've done enough to clean up after myself, I don't know. Any advice would be greatly appreciated.. I imagine that once children come in the mix I would increment their refcount in the setter, and decrement this in the destructor - which might trigger their destruction recursively.

Apologies for the long "first" post. I used to be user "rvosa" but forgot my password and lost my email address. Thanks!


In reply to Inline::C self-referential struct idioms and memory by rutgeraldo

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.