Discussion:
perl binding for C++ ref-counted object
(too old to reply)
YangXi
2011-10-17 03:25:39 UTC
Permalink
Hi, everyone!I'm asking a question about how to wrapping a refcounted class inside perl.I have some experience on embedding perl in C++, but have little knowledge on perl XS, and I found perldoc perlxs really puzzled.Firstly, I have an simple refcounted C++ base class like this:class Referenced {public: Referenced():refcnt(0) { } virtual ~Referenced() {} void refInc() { refcnt++; } void refDec() { if (--refcnt<=0) delete this; }protected: int refcnt;};In my wrapper, I want to have following functions:- able to construct my object within perl, like My::Class->new();- able to construct my object in C++, and pass it to perl sub as argument;- handle ref count correctly;So, is these things correct for my XS?Referenced::new(class) PREINIT: const char* class; Referenced* obj; SV* obj_wrap; SV* sv; CODE: // create object obj = new Referenced; obj->refInc(); // store pointer as unsigned int? obj_wrap = newSV(0); sv_setuv(obj_wrap, (uv)obj); // we always wrap 2 layers SVs for a class? Should I do these things manually? sv = newSVrv(obj_wrap, class); RETVAL = sv; OUTPUT: RETVAL// is this correct?// I don't really understand when would Perl do automatic scalar conversion, and when should I manually do that.Referenced::DESTROY(self) PREINIT: Referenced* self; CODE: self->refDec();
Steffen Mueller
2011-10-20 06:42:13 UTC
Permalink
Hi YanXi,
Post by YangXi
I'm asking a question about how to wrapping a refcounted class inside perl.
I have some experience on embedding perl in C++, but have little
knowledge on perl XS, and I found perldoc perlxs really puzzled.
I'm sorry that this isn't a solution for your problem, but maybe it's
helpful nonetheless. Object ownership and refcounts are something
extremely nasty to deal with when interfacing between two languages that
have a very different view of it. For this reason, it's easiest not to
have C++ do the refcounting at all. I understand that this might not be
possible in your case.

If you just have a regular, non-refcounting object in C++, you can
easily use typemaps like O_OBJECT from

http://cpansearch.perl.org/src/MBARBON/ExtUtils-XSpp-0.1602/examples/Object-WithIntAndString/perlobject.map

to have the object wrapped into a Perl scalar. The C++ object will be
owned by that scalar and the refcount will be perl's refcount of the
SV*. In that case a simple DESTROY XS method will suffice along the
lines of the DESTROY here:

http://cpansearch.perl.org/src/SMUELLER/Math-SimpleHisto-XS-1.23/XS.xs

The macro in that case can often be replaced by "delete self" for C++
objects.

I hope this has some general pointers that help a bit.

Best regards,
Steffen
Marvin Humphrey
2011-10-21 10:55:08 UTC
Permalink
I've got a more nasty idea: all I need is refcount and garbage collection,
so I can just embed an perl HV inside my object, and use the reference count
of that HV. Woo! Too ugly!
Haha, this is a technique that we use in Clownfish, the object model used by
Apache Lucy (which is C rather than C++, but needs to solve similar problems).

Your C++ refcount manipulation methods will need to wrap invocations of
SvREFCNT_dec(), SvREFCNT_inc(), and SvREFCNT(), and you need an XS DESTROY
method which invokes the C++ destructor.

The key is, as you have surmised, maintaining a unified refcount for the
combination of a Perl object and a C++ object which point to each other.

Here's the code which implements our refcount manipulation routines:

http://svn.apache.org/repos/asf/incubator/lucy/trunk/perl/xs/Lucy/Object/Obj.c

And here's a thread on the Lucy developer's list where the design was
discussed:

http://lucy.markmail.org/message/jkst23okksyynzss

Our code is probably more complex than than yours will be because we lazily
create the Perl object only when the refcount reaches 4 or it's needed because
access has been requested from Perl-space. We also use only the inner portion
of a Perl blessed scalar, avoiding the outer RV.

Marvin Humphrey

Loading...