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