This works for dynamically allocating memory (an array of char):
SV * create_image(int size) { char * image; New(0,image,size,char); memset(image,CLEAR,size); return sv_setref_pv(newSViv(0),"image", (void *)image); }
void destroy_image(SV * p) { char * image = (char *) SvIV(SvRV(p)); Safefree(image); }
Since you have blessed the reference into package 'image', wouldn't that mean that you would never explicitly call 'destroy_image()' ?
Rather, if I'm not mistaken, you would simply rename 'destroy_image()' to 'DESTROY()' and it would be called automatically for you whenever the reference went out of scope.
I've just been playing around with this aspect - and it seems to work that way.
One thing that puzzles me is that if I explicitly call a destroy() function on a blessed reference, then DESTROY() still gets automatically called - ie the reference apparently gets Safefreed twice. I would expect that such an occurrence should produce an error, but I find that it doesn't.
I also expected that if the reference has been blessed into a package, but there was no 'DESTROY()' function to be found, then perl would complain about that. But that's not the case either :-)
Below is a simple (though not-so-small) demo script of what I'm talking about if anyone is interested .... or even if they're not :-)
Cheers, Rob
use warnings;
########################################
# Example 1: Unblessed # Free the memory at each iteration - which I presume is the # correct thing to do.
for(1..10) {
$x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
$y = int(rand(13)) + 1;
$z = Hmmmm::create_struct($x, $y);
Hmmmm::clear_mem($z);
}print "\n1111\n\n";
########################################
# Example 2: Unblessed # Same as example 1, but memory is *not* freed at each # iteration which, I presume, could lead to memory leaks.
for(1..10) {
$x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
$y = int(rand(13)) + 1;
$zz = Hmmmm::create_struct($x, $y);
}Hmmmm::clear_mem($zz);
print "\n2222\n\n";
########################################
# Example 3: Blessed # No need to free the memory as Hmmmm::DESTROY() is called # automatically when needed. This loop prints out "DESTROY() has # been called" 9 times, as is to be expected.
for(1..10) {
$x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
$y = int(rand(13)) + 1;
$zzz = Hmmmm::create_struct_blessed($x, $y);
}print "\n3333\n\n";
########################################
# Example 4: Blessed # Exactly the same as Example 3 - only this time we see "DESTROY() # has been called" 10 times, as is to be expected
for(1..10) {
$x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
$y = int(rand(13)) + 1;
$zzz = Hmmmm::create_struct_blessed($x, $y);
}print "\n4444\n\n";
########################################
# Example 5: Blessed # The same as Examples 3 & 4 - only this time we explicitly call #'Hmmmm::clear_mem()' && # DESTROY() also gets automatically called. # Surprisingly (to me) this does not produce any errors
for(1..10) {
$x = ('Hearts', 'Spades', 'Clubs', 'Diamonds')[rand(4)];
$y = int(rand(13)) + 1;
$zzzz = Hmmmm::create_struct_blessed($x, $y);
Hmmmm::clear_mem($zzzz);
# @h = Hmmmm::deref_ref($zzzz);
# print "@h\n";
}print "\n5555\n\n";
########################################
# Now, just prior to exit, $zzz and $zzzz are DESTROY()ed.
package Hmmmm;
use Inline (C => Config =>
BUILD_NOISY => 1,
);use Inline C => <<'EOC';
typedef struct {
SV * suit;
int value;
} Card;
SV * create_struct(SV * s, int v) { Card * cptr;
New(123, cptr, sizeof(Card), Card);
if(cptr == NULL) croak("Failed to allocate memory in create_struct function");
cptr->suit = s;
cptr->value = v;
return sv_setref_pv(newSViv(0), Nullch, cptr);}
SV * create_struct_blessed(SV * s, int v) {
Card * cptr;New(123, cptr, sizeof(Card), Card);
if(cptr == NULL) croak("Failed to allocate memory in create_struct function");
cptr->suit = s;
cptr->value = v;
return sv_setref_pv(newSViv(0), "Hmmmm", cptr);}
void deref_ref(SV * p) {
Inline_Stack_Vars; Inline_Stack_Reset;
Inline_Stack_Push( ((Card *)SvIV(SvRV(p)))->suit );
Inline_Stack_Push(newSViv(((Card *)SvIV(SvRV(p)))->value));
Inline_Stack_Done;
Inline_Stack_Return(2);}
void clear_mem(SV * p) {
Card* c = (Card *)SvIV(SvRV(p));
printf("Clear_mem called\n");
Safefree(c->suit);
/* c->value is an int, and not to be Safefreed */
Safefree(c);
}void DESTROY(SV * p) {
Card* c = (Card *)SvIV(SvRV(p));
printf("DESTROY() has been called\n");
Safefree(c->suit);
/* c->value is an int, and not to be Safefreed */
Safefree(c);
}EOC
