Ok. You didn't mention there was deep nesting.
Somewhat less "hacky" than relying on the NV slot to not get overwritten by Perl, could you you live with an extra layer of indirection? That is, each time you get an unfree-able pointer, allocate a control structure to point to the unfree-able structure. This control structure would also have a field to hold the pointer you were going to put in the NV slot (plus any other fields you might need).
| [reply] |
Yeah ... That's the same solution as Corion suggested above. Just not as an extra indirection in the Perl layer, but at the C layer.
So now there's 3 solutions. All of them keeping a reference to the "owning" C object.
- Make the objects plain C pointers and keep the reference in the NV slot
- Make the objects an extra C indirection struct and keep the reference in that
- Make the objects ordinary Perl blessed hashrefs and keep a reference in there to the "parent" perl object ... when will then not have it's DESTROY called before the child is gone.
I think all of them will work, but I still wonder what Perl actually guarantees about dualvalue SVs. Since its practicaly encouraged by Scarlar::Util, I would have expected such a statement in perlapi or perlguts.
To put it further into perspective. Here's Devel::Peek description of the T_PTROBJ typemap SV.. As it clearly shows, the PV and NV slots are empty (as standard). But what happens if you use them?
| [reply] |
Still no guarantee what Perl might do to those slots. I would hesitate to rely being left alone, especially in future versions of Perl.
| [reply] |
I would go so far as to predict rather-emphatically that it wouldn’t. And, in any case, it would be highly dependent upon (read: “would introduce a whale of a dependency upon ...”) the exact internal implementations of that library. Warning-bells going off all over the place here.
Also worth heavy consideration here is the temporal issue: having been given a live memory-address, how long is that address actually going to be “good?” Your Perl app could now potentially modify (read: “muck around with”) that memory at any future-time. How predictably-stable do we consider that situation to be? In other words, how bad are the nasty-bugs going to be, if when they start to occur? These are design considerations that, to my way of thinking, absolutely overwhelm most all other concerns most of the time. So to speak, “I don’t really care if it screws-up ‘very quickly.’ ” I care that the solution is robust and thoroughly diagnosable. (And yes, it depends entirely upon the library.)
| |
I would go so far as to predict rather-emphatically that it wouldn’t. And, in any case, it would be highly dependent upon (read: “would introduce a whale of a dependency upon ...”) the exact internal implementations of that library. Warning-bells going off all over the place here.
I agree fully. Unless the library provided **deep copy** routines for every relevant struct, this is not going to work.
having been given a live memory-address, how long is that address actually going to be “good?” Your Perl app could now potentially modify (read: “muck around with”) that memory at any future-time.
First: The scenario is that the C library doesn't make any requirements about when the correct free function is called. Only that it should be called. In C that would often (but not always) lead to symmetric allocations/de-allocations to prevent leaks, but there's nothing to say that free_*() can't be called at any time later at the will of a reference count engine.
Secondly: You have alluded to the Perl app "mucking around" earlier. I don't really share that concern. I mean... any Perl module will break spectaculary if the Perl app started trashing its objects. Take the JSON::XS module. What would happen if I did:
my $json = new JSON::XS;
substr($$json,0,1) = 'X'; # the object is a ref to a PV
I would simply set a byte in the start of *JSON on the C side.
No module needs to protect against a perl app using anything but the defined API on the objects/vars it return.
| [reply] [d/l] |