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

Reply via email to