They give you a half-way solution
I wonder why do they do that ? If I can use overload '=' => \© then that ought to do something useful. (Ok ... so perhaps, in the right hands, it does do something useful.) And why is it considered un-perlish to overload '=' ? (Well ... I probably wouldn't understand the answer to that question, anyway.)
call your copy function directly instead of trying to overload '='
Yes - that's pretty much what the demo I posted does. Except that it contains an unnecessary function. The 'set_from_existing' function can be removed from the Inline::C section, the perl code in the script changed to:
$num1 = Grief::new(113);
$num2 = $num1; # Assign using _copy()
$num3 = _copy($num1, '', ''); # Assign using _copy()
_set_val($num1, 555);
print _get_val($num2),"\n", _get_val($num3), "\n";
and the rest of the post remains essentially unchanged. It still baffles me that $num3 gets created as a separate object, but $num2 gets created (by exactly the same function) as some sort of semi-object that (to begin with) is tied in some way to $num1, and never gets DESTROYed (even if the tie is subsequently broken).
Thanks Paul. I can see no reason to disagree with your advice.
Cheers, Rob | [reply] [d/l] [select] |
SV * _copy( SV * arg_obj, SV * second, SV * third ) {
Number * num_obj;
SV * obj_ref, * obj;
printf( "_copy:%p %p %p\n", arg_obj, second, third );
...
SV * _set_from_existing( SV * arg_obj ) {
Number * num_obj;
SV * obj_ref, * obj;
printf( "_set::%p\n", arg_obj );
...
And it appears that the overloading is not causing your _copy() function to be called:
Finished Build Compile Stage
_set::0185E260
555
113
Destroying ...... destroyed
Destroying ...... destroyed
Which (as best I can tell) explains the output completely:
$$num1 = Grief::new( 113 );
$num2 = $num1; # Assign using _copy( )
$num3 = _set_from_existing( $num1 ); # Assign using _set_from_existing
+( )
_set_val( $num1, 555 );
print _get_val( $num2 ),"\n", _get_val( $num3 ), "\n";
__END__
$num2, in the absence of the overloading is simply an alias to $num1, whereas $num3 is explicitely as new object with the same value. When you set $num1 to 555, you are also setting $num2, as they are both references to the same object.
All of which is probably not news to you. The only real question as far as I can see is if overload can't or won't allow you to overload assignment, why doesn't use overload '=' => \&_copy; throw an error?
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.
| [reply] [d/l] [select] |
And it appears that the overloading is not causing your _copy() function to be called
Damn!! ... that's the oversight I was ... ummmm ... overlooking. I should've thought to stick a printf() in there as a check. Thanks for picking that up.
Another approach is to simply comment out the 'use overload ...' code - which has no effect on the output of the script at all. Oh, well .... live and learn ....
why doesn't use overload '=' => \&_copy; throw an error?
Good question. Thanks BrowserUK.
Cheers, Rob Update: I think, at last, I start to see the light. The overloading of the assignment operator takes its effect only when the value of either $num1 or $num2 is subsequently altered using an overloaded operator. Consider the following:
use warnings;
use Devel::Peek;
package Grief;
use overload
'++' => \&_inc,
'=' => \&_copy,
;
use Inline C => Config =>
BUILD_NOISY => 1;
use Inline C => <<'EOC';
typedef struct {
long num;
} Number;
SV * new(SV * x) {
Number * num_obj;
SV * obj_ref, * obj;
New(1, num_obj, 1, Number);
if(num_obj == NULL)
croak("Failed to allocate memory in new() function");
obj_ref = newSViv(0);
obj = newSVrv(obj_ref, "Grief");
num_obj->num = SvUV(x);
sv_setiv(obj, (IV)num_obj);
SvREADONLY_on(obj);
return obj_ref;
}
SV * _get_val(SV * obj) {
return newSVuv(((Number*)SvIV(SvRV(obj)))->num);
}
void _inc(SV * obj, SV * second, SV * third) {
(((Number*)SvIV(SvRV(obj)))->num)++;
}
SV * _copy(SV * arg_obj, SV * second, SV * third) {
Number * num_obj;
SV * obj_ref, * obj;
printf( "_copy:%p %p %p\n", arg_obj, second, third );
New(1, num_obj, 1, Number);
if(num_obj == NULL)
croak("Failed to allocate memory in _copy() function");
obj_ref = newSViv(0);
obj = newSVrv(obj_ref, "Grief");
num_obj->num = ((Number*)SvIV(SvRV(arg_obj)))->num;
sv_setiv(obj, (IV)num_obj);
SvREADONLY_on(obj);
return obj_ref;
}
void DESTROY(SV * obj) {
printf("Destroying ...");
Number * number = (Number*)SvIV(SvRV(obj));
Safefree(number);
printf("... destroyed\n");
}
EOC
$num1 = Grief::new(113);
$num2 = $num1;
$num3 = _copy($num1, '', '');
#Run any one of the following 4 lines
$num1++; # _copy() gets called, 3 objects DESTROYed
#$num2++; # _copy() gets called, 3 objects DESTROYed
#_inc($num1, '', ''); # no _copy(), 2 objects DESTROYed
#_inc($num2, '', ''); # no _copy(), 2 objects DESTROYed
print _get_val($num2)," | ", _get_val($num3), "\n";
| [reply] [d/l] [select] |