----- 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__