Marcus Holland-Moritz <[EMAIL PROTECTED]> writes: >I'm wondering if someone else ever wanted to do this... > >Deep inside my XS module I create an object and pass it to >a function (which may pass it to other functions and so on). >However, any of these functions may call Perl_croak(), and >if they do, I need to destroy the object if I don't want to >leak memory. Here's an excerpt of the original code: > > tag = tag_new(tagid, gs_TagTbl[tagid].vtbl); > rv = gs_TagTbl[tagid].set(aTHX_ ptti, tag, val); > insert_tag(ptl, tag); > >Calling the 'set' method in the second line may eventually >call croak(). If it does, I just want to throw away the tag >object and croak() again. > >I didn't find anything in perl(xs|guts|call|api), so I looked >at how "eval" does it, and came up with the following macros: > > #define dXCPT dJMPENV; int rEtV = 0 > > #define XCPT_TRY_START JMPENV_PUSH(rEtV); \ > if (rEtV == 0) > > #define XCPT_TRY_END JMPENV_POP; > > #define XCPT_CATCH if (rEtV != 0) > > #define XCPT_RETHROW JMPENV_JUMP(rEtV) > >With these macros, I can rewrite the above code as: > > dXCPT; > > tag = tag_new(tagid, gs_TagTbl[tagid].vtbl); > > XCPT_TRY_START { > rv = gs_TagTbl[tagid].set(aTHX_ ptti, tag, val); > } XCPT_TRY_END > > XCPT_CATCH > { > tag_delete(tag); > XCPT_RETHROW; > } > > insert_tag(ptl, tag); > >This seems to work fine, but makes use of internal API.
Which is why I have to date avoid this and done this kind of thing one of two ways: A. Make the "object" a perl level object (as well) and give the perl class a DESTROY method which discards the C/C++ objuect. B. Wrap the callback (your .set) in a perl XS 'cv' and call that via call_sv(cv,G_EVAL) and the test SvTRUE(ERRSV) > >Is this the way to do it? I am not entirely sure. >Or is there any other/better way? Two other ways above... > >If it turns out to be correct, would it make sense to document >it and/or add some public interface for this purpose? That would be good. > >Marcus