I have a C++ class wrapped with SWIG. It works nicely and doesn't leak memory when I create and destroy lots of objects normally.

But the class has a method that returns a std::vector containing several new instances of the class which are variants of itself.

It almost works -- the SWIG wrapper returns an array reference to the Perl caller, but the objects in the array leak memory when they are destroyed.

This is correct behavior on SWIGs part, as the objects were created by C++, not SWIG or Perl. I want to plug the leak by calling ACQUIRE for each object, which will cause Perl to explicity call the C++ destructor via the DESTROY function created by SWIG.

Unlike normally-created objects which are HASHes, the objects delivered in the array are SCALARs:

my $f = Foo->new(); # normal creation print ref $f; # prints "Foo" print $f; # prints "Foo=HASH(0x19a0ef8)" my $aref = $f->getVariants(); # reference to array containing many Foo +s print ref $aref->[0]; # prints "Foo" print $aref->[0]; # prints "Foo=SCALAR(0x19c8290)"

Not surprisingly, calling ACQUIRE with one of the SCALARS gives the error "Not a HASH reference at..." when it tries to call tied, since the ACQUIRE method generated by SWIG assumes a HASH. Here's the SWIG-generated Perl for class Foo:

package Bar::Foo; use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS); @ISA = qw( Bar ); %OWNER = (); %ITERATORS = (); sub new { my $pkg = shift; my $self = Barc::new_Foo(@_); bless $self, $pkg if defined($self); } sub DESTROY { return unless $_[0]->isa('HASH'); my $self = tied(%{$_[0]}); return unless defined $self; delete $ITERATORS{$self}; if (exists $OWNER{$self}) { Barc::delete_Foo($self); delete $OWNER{$self}; } } *AllVariants = *Barc::Foo_AllVariants; sub DISOWN { my $self = shift; my $ptr = tied(%$self); delete $OWNER{$ptr}; } sub ACQUIRE { my $self = shift; my $ptr = tied(%$self); $OWNER{$ptr} = 1; }

For reference, here are the lines from the SWIG-generated C++ wrapper that appear to create the Foo objects.

The first line appears in the wrapper for the new method. The second line is from the wrapper for the method returning the array of objects:

SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Foo, SWIG_OWNER + | SWIG_SHADOW) SWIG_NewPointerObj(x, SWIGTYPE_p_Foo, 0)

I could make a Perl-specific helper class in C++ with a getNext method which could then be used by a Perl method in the wrapper, like so:

%perlcode %{ sub getAllVariants { my ($self) = @_; my $fv = FooVariants->new($self); my $aref = []; while ( my $foo = $fv->getNext() ) { $foo->ACQUIRE(); # C++ code does not delete this, so ensure del +ete_ method is called push( @$aref, $foo ); } return $aref; } %}

I know this technique works, but I'd prefer an all-Perl method. Is there a way to change a SCALAR into a HASH using just Perl without any XS or C++ code?


In reply to Change a SCALAR into a HASH using just Perl without any XS code? by tod222

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.