in reply to Re^2: perl embedded in C++: how to undefine perl objects that are blessed references to C++ objects when the C++ object destructs
in thread perl embedded in C++: how to undefine perl objects that are blessed references to C++ objects when the C++ object destructs

I'm far from expert on Perl internals, but given the way Perl allocates it variables I think that this would necessitate scanning the entire stack and entire heap attempting to find values in memory locations that 'look like' the SV* in question. Besides being rather slow, it is fraught with dangers.

What would you search for? How would you distinguish between four bytes that contain the address of your C++ object, and four bytes that contain a number that coincidentally matches the address of your C++ object?

And what benefit would you get? If the Perl code is going to indirect through a retained SV* and so trap; if you set it to undef, it is still going to indirect through it and die anyway. It might be a less violent death, but there is still no way for the Perl code to reasonably continue.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP PCW It is as I've been saying!(Audio until 20090817)
  • Comment on Re^3: perl embedded in C++: how to undefine perl objects that are blessed references to C++ objects when the C++ object destructs

Replies are listed 'Best First'.
Re^4: perl embedded in C++: how to undefine perl objects that are blessed references to C++ objects when the C++ object destructs
by kingkongrevenge (Scribe) on Sep 21, 2009 at 20:19 UTC
    Follow Up: I changed the perl class interfaces to C++ objects to be blessed references TO an SV reference to the the object pointer.
    ThePerlClass=(BlessedSvRef) -> UnblessedSvRef -> theCppObjPointer

    I only had to add the extra layer of indirection in the typemap and everything continued to work.

    When the C++ destructor for the relevant object is called, it sets the one and only copy of UnblessedSvRef to null. Any copies of the perl object floating around now just point to undef, which fails with a fathomable explanation (and a catchable exception) rather than catastrophically. When the last BlessedSvRef goes out of scope the ref count of UnblessedSvRef goes to zero and it's destroyed.

    I overloaded the bool operator to test for undef in UnblessedSvRef.

    I also overloaded the dereference operator so it's impossible for the user to get to the underlying UnblessedSvRef and store a pointer that can end up invalid.

      Thanks for the update. I wish more OPs would do this.

      What you're doing sounds intriguing, but I'm having trouble visualising it. I don't supppose you fancy posting it do you? Not the whole thing, just the (relavent parts of) the construictor and destructor would be most interesting.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        My perly C++ objects all inherit from PClass.

        Interesting bit of the PClass constructor:

        /* The SV holding the pointer to the actual object is hidden away +in the interpreter. Users aren't supposed to be able to get at it. * +/ SV* theObjRef = newSV(0); sv_setref_pv( theObjRef, 0, (void*)this ); /* Now we bless a reference to theObj. * PClasses are not hashrefs like normal perl classes. They are a + blessed * reference to a pointer to a C++ obj. Phew! * Stuff in the typemap deals with dereferencing the blessed refer +ence. */ SV* theRef = newRV_noinc(theObjRef); //Make a reference to the ref +erence. noinc: when the last reference is gone, theObj should disapp +ear. sv_bless( theRef, gv_stashpv(name.c_str(), GV_ADD) ); sv_setsv(svrep.sv, theRef); # svrep is member var. Its type is j +ust a little convenience wrapper around SV* with some RAII stuff. if (name != "PClass") { // Tell the class on the perl side that it inherits from PClas +s. std::string class_isa = name + std::string("::ISA"); av_push( get_av(class_isa.c_str(), 1), newSVpv("PClass", 0) ); // If the user provided an XS method to pull XS methods into t +he perl interpreter, call that. if (booterSub) _bootModule(name, booterSub); // If a "name".pm is in the @INC path, try to load it up. // eval_pv(std::string(std::string("eval qq{ use ") + n +ame + "}").c_str(), true); }

        Interesting bit of the PClass destructor. After this is run all copies of the PClass on the perl side now point to undef and any member functions will will bitch about it:

        sv_setsv(SvRV(svrep.sv), Nullsv);

        PClass dereference (${}) is overloaded to only return a reference to self. No real dereferencing possible from the perl side:

        RETVAL = newRV_inc(lobj);

        PClass bool context is overloaded to test for undef in the referenced SV:

        RETVAL = SvOK(SvRV(lobj));

        The typemap:

        TYPEMAP PClass* CPP_OBJECT OUTPUT CPP_OBJECT SV* theObjRef = newSV(0); sv_setref_pv( theObjRef, 0, (void*)$var ); SV* rv = newRV_noinc(theObjRef); sv_bless( rv, gv_stashpv(CLASS, GV_ADD) ); sv_setsv($arg, rv); INPUT CPP_OBJECT $var = ($type) SvIV(SvRV((SV*)SvRV($arg)));

        Then pretty standard C++ style XS works fine elsewhere:

        bool PClass::some_func() CODE: RETVAL = THIS->someCppFunc(); OUTPUT: RETVAL

        To give a C++ object a perl interface you inherit from PClass, define the XS, and add it to the typemap as a CPP_OBJECT. Then you can pass the objects to perl code that can interact with it.