syphilis has asked for the wisdom of the Perl Monks concerning the following question:
And that works fine - but it occurred to me that I should be able to rewrite the function as in 'in place' operation (ie one that did not return anything) so I rewrote it as:SV * overload_add_eq(SV * obj, SV * addon, SV * third) { Card* c = (Card *)SvIV(SvRV(obj)); SvREFCNT_inc(obj); c->value += SvIV(addon); return obj; }
Now, when I do $obj += $addon; windows intervenes to tell me that perl.exe has stopped working (but fails to come up with any other information). On linux I get a segfault. Interestingly, I find that this modified 'overload_add_eq' works fine (on both linux and windows) when invoked explicitly in perl code as overload_add_eq($obj, $addon, 0);. It's only when it's invoked by the overload mechanism that the problem arises. Anyone know why that is, and what to do about it ?void overload_add_eq(SV * obj, SV * addon, SV * third) { Card* c = (Card *)SvIV(SvRV(obj)); c->value += SvIV(addon); }
use warnings; package My_struct; use Inline (C => Config => BUILD_NOISY => 1, ); use Inline C => <<'EOC'; typedef struct { char * suit; int value; } Card; SV * create_struct(SV * s, SV * v) { Card * cptr; New(123, cptr, sizeof(Card), Card); if(cptr == NULL) croak("Failed to allocate memory in create_struc +t function"); cptr->suit = SvPV_nolen(s); cptr->value = SvIV(v); return sv_setref_pv(newSViv(0), "My_struct", cptr); } void deref_ref(SV * obj) { Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push(newSVpv(((Card *)SvIV(SvRV(obj)))->suit, 0)); Inline_Stack_Push(newSViv(((Card *)SvIV(SvRV(obj)))->value)); Inline_Stack_Done; Inline_Stack_Return(2); } void DESTROY(SV * obj) { printf("Destroying ..."); Card* c = (Card *)SvIV(SvRV(obj)); Safefree(c); printf("...destroyed\n"); } void overload_add_eq(SV * obj, SV * addon, SV * third) { Card* c = (Card *)SvIV(SvRV(obj)); // SvREFCNT_inc(obj); c->value += SvIV(addon); // return obj; } EOC use overload '+=' => \&overload_add_eq; $suit = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)]; $value = int(rand(13)) + 1; $obj = create_struct($suit, $value); $addon = 5; @members = deref_ref($obj); print "@members\n"; #$obj += $addon; # Crashes overload_add_eq($obj, $addon, 0); @members = deref_ref($obj); print "@members\n";
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Overload '+=' with XSub
by Anno (Deacon) on Mar 29, 2007 at 09:34 UTC | |
by syphilis (Archbishop) on Mar 29, 2007 at 10:33 UTC | |
by Anno (Deacon) on Mar 29, 2007 at 10:51 UTC | |
by syphilis (Archbishop) on Mar 29, 2007 at 12:21 UTC | |
by Anno (Deacon) on Mar 29, 2007 at 17:30 UTC | |
by Trizor (Pilgrim) on Mar 29, 2007 at 11:31 UTC | |
by syphilis (Archbishop) on Mar 29, 2007 at 12:39 UTC |