----- Original Message -----
From: "Eric Wilhelm" <[EMAIL PROTECTED]>
> You *could* add some sort of flag to your struct and an if() to
> DESTROY(). Alternatively, you could write DESTROY() in perl and call
> one of two C methods from there.
>
I can't see how adding a flag to the struct will help - because DESTROY()
won't be able to access that flag until it has first determined whether the
struct is a Civilian or a Soldier - and that's the bit I can't work out. How
can DESTROY() determine whether the argument it has received is a Civilian
object or a Soldier object ?
In other words,DESTROY() receives as its argument a SV*:
DESTROY(SV * obj) {// do stuff}
How does DESTROY() then determine whether it needs to do:
Soldier* soldier = (Soldier*)SvIV(SvRV(obj));
or:
Civilian* civilian = (Civilian*)SvIV(SvRV(obj));
> But most would argue that the civilian is not the same as a soldier?
>
> Presumably you have a set of methods that works on both of them?
>
> I haven't tried it, but what about inheritance? If Civilian @ISA
> Soldier, then you just override new() and DESTROY() right? You would
> need another constructor anyway to get a different struct.
>
Yep - 2 different constructors, different methods, and inheritance is not an
issue (in this particular instance).
Turns out that the 'soldier' example in the cookbook is a bad one to quote
because even in its original form it tries to "Free to wrong pool..." when
DESTROY() gets called (Win32, perl 5.8.7). Below is a modified form of that
script that hints at what I'm asking about. Afaik, the Devel::Peek::Dump()s
of both the Soldier object and the Civilian object don't reveal anything
that DESTROY() could use to determine whether it's dealing with a Soldier
object or a Civilian object.
To get rid of the "Free to wrong pool..." error, I've deleted the free()ing
of the 2 struct elements from DESTROY(). Is that the correct fix?
For some reason *both* the Civilian objects and the Soldier objects now get
DESTROY()ed without error (for me anyway) - but surely the job is not being
done correctly ??
Cheers,
Rob
use warnings;
use Devel::Peek;
package Soldier_Civilian;
use Inline C => Config =>
BUILD_NOISY => 1;
use Inline C => <<'END';
typedef struct {
char* name;
char* rank;
long serial;
} Soldier;
typedef struct {
char* surname;
char* address;
char* occupation;
long age;
} Civilian;
SV* new_soldier(char* name, char* rank, long serial) {
Soldier* soldier = malloc(sizeof(Soldier));
SV* obj_ref = newSViv(0);
SV* obj = newSVrv(obj_ref, "Soldier_Civilian");
soldier->name = strdup(name);
soldier->rank = strdup(rank);
soldier->serial = serial;
sv_setiv(obj, (IV)soldier);
SvREADONLY_on(obj);
return obj_ref;
}
SV* new_civilian(char* surname, char* address, char* occupation, long age) {
Civilian* civilian = malloc(sizeof(Civilian));
SV* obj_ref = newSViv(0);
SV* obj = newSVrv(obj_ref, "Soldier_Civilian");
civilian->surname = strdup(surname);
civilian->address = strdup(address);
civilian->occupation = strdup(occupation);
civilian->age = age;
sv_setiv(obj, (IV)civilian);
SvREADONLY_on(obj);
return obj_ref;
}
char* get_name(SV* obj) {
return ((Soldier*)SvIV(SvRV(obj)))->name;
}
char* get_rank(SV* obj) {
return ((Soldier*)SvIV(SvRV(obj)))->rank;
}
long get_serial(SV* obj) {
return ((Soldier*)SvIV(SvRV(obj)))->serial;
}
char* get_surname(SV* obj) {
return ((Civilian*)SvIV(SvRV(obj)))->surname;
}
char* get_address(SV* obj) {
return ((Civilian*)SvIV(SvRV(obj)))->address;
}
char* get_occupation(SV* obj) {
return ((Civilian*)SvIV(SvRV(obj)))->occupation;
}
long get_age(SV* obj) {
return ((Civilian*)SvIV(SvRV(obj)))->age;
}
void DESTROY(SV* obj) {
printf("Destroying..");
Soldier* soldier = (Soldier*)SvIV(SvRV(obj));
free(soldier);
printf("..destroyed\n");
}
END
$obj1 = new_soldier('Benjamin', 'Private', 11111);
$obj2 = new_soldier('Sanders', 'Colonel', 22222);
$obj3 = new_soldier('Matt', 'Sergeant', 33333);
for $obj ($obj1, $obj2, $obj3) {
print($obj->get_serial, " ",
$obj->get_name, " is a ",
$obj->get_rank, "\n");
}
$obj4 = new_civilian('Ben', 'here', 'unemployed', 11);
$obj5 = new_civilian('Stan', 'there', 'self-employed', 22);
$obj6 = new_civilian('Matt', 'everywhere', 'self-unemployed', 33);
for $obj ($obj4, $obj5, $obj6) {
print($obj->get_address, " ",
$obj->get_surname, " ",
$obj->get_occupation, " ",
$obj->get_age, "\n");
}
print "#########\n";
Devel::Peek::Dump($obj1);
print "#########\n";
Devel::Peek::Dump($obj4);
__END__