> I am trying to write an xs interface to an external library.  
> My code takes two perl arrays, allocates and populates 
> corresponding C structures, and passes them to the library routine.
> The problem is that the program is unstable.  It will sometimes 
> cause core dumps in the external library.  The library in itself 
> is believed to be stable, so it seems to be something in the 
> perl/C interface.

Here is more of the code.  see Classify(rvAnimals, rvPlants, count) below:

thanks,
Tamar

_________________________________________________________

void 
setDouble(HV * hv, char * fieldName, double val)
{
  SV ** sv = hv_fetch(hv, fieldName, strlen(fieldName), FALSE);
  if(!SvOK(*sv)) {
        printf("Error - hv_fetch %s returned bad sv\n", fieldName);
  }
  sv_setnv(*sv, val);
}

void
setLong(HV * hv, char * fieldName, long val)
{
  SV ** sv = hv_fetch(hv, fieldName, strlen(fieldName), FALSE);
  if(!SvOK(*sv)) {
        printf("Error - hv_fetch %s returned bad sv\n", fieldName);
  }
  sv_setiv(*sv, val);
}

/* 
   populate the fields of 
       animal
   from 
       hvAnimal (perl hash value)
*/
void
MakeAanimal(HV * hvAnimal, Aanimal * animal)
{
  SV ** sv;

  /* string */
  char * str = getString(hvAnimal, "strField");
  strlcpy(animal->strField, str, sizeof(animal->strField));

  /* long */
  animal->longField = getLong(hvAnimal, "longField");

  /* double */
  animal->doubleField = getDouble(hvAnimal, "doubleField");

  /* initialize some fields that the library will write */
  animal->field4 = 0.0;
  animal->field5 = 0.0;
  animal->status = 0;
}


MODULE = Animals                PACKAGE = Animals

int
Classify(rvAnimals, rvPlants, count)
     SV * rvAnimals
     SV * rvPlants
     SV * count
  PROTOTYPE: $$$
  PREINIT:       
         long i, rc;
         AV *avAnimals, *avPlants;
         AallAnimals A;   /* &A , &P to be passed to library function */
         AallPlants P;
  CODE:
     /* get avAnimals from rvAnimals and
            avPlants from rvPlants
     */
         if (SvROK(rvAnimals) && SvTYPE(SvRV(rvAnimals)) == SVt_PVAV &&
                 SvROK(rvPlants) && SvTYPE(SvRV(rvPlants)) == SVt_PVAV) 
         {
                avAnimals = (AV*)SvRV(rvAnimals);
                avPlants = (AV*)SvRV(rvPlants);
         }
         else 
         {
                printf("unexpected animals or plants arrays\n");
                XSRETURN_UNDEF;
         } 

         /* determine number of animals and plants */
         /* av_len returns the highest index in the array */
        A.lNumAnimals = av_len(avAnimals) + 1;
        P.lNumPlants = av_len(avPlants) + 1;

         /* allocate memory for the corresponding C animals and plants */
        New(0, A.animal, A.lNumAnimals, Aanimal);
        if (!A.animal) 
        {
        Perl_croak("Error - could not allocate animals array\n");
        }
         
        New(0, P.plant, P.lNumPlants, Aplant);
        if (!P.plant) 
        {
        Perl_croak("Error - could not allocate plants array\n");
        }

         /* copy data over from input variables to C structures */
         /*  ANIMALS */
        for(i = 0; i < A.lNumAnimals; i++)
        {
                SV ** svAnimal = av_fetch(avAnimals, i, FALSE);
                /* the animal is a blessed reference to a hash */
                HV * hvAnimal;
                if(SvROK(*svAnimal) && SvTYPE(SvRV(*svAnimal)) == SVt_PVHV)
                hvAnimal = (HV*)(SvRV(*svAnimal));
                else 
                   Perl_croak("Unexpected animals array\n");
                MakeAanimal(hvAnimal, A.animal+i);
         }
         /*  PLANTS */
         for(i = 0; i < P.lNumPlants; i++)
         {
                SV ** svPlant = av_fetch(avPlants, i, FALSE);
                /* the plant is a blessed reference to a hash */
                HV * hvPlant;
                if(SvROK(*svPlant) && SvTYPE(SvRV(*svPlant)) == SVt_PVHV)
                hvPlant = (HV*)(SvRV(*svPlant));
                else 
                   Perl_croak("Unexpected plants array\n");
        MakeAplant(hvPlant, P.plant+i);
         }

        /* library function call -- will write results in animals and plants 
structures */
        AnimalClassification(&A, &P);

        /* copy data back into perl structures */
        /*  ANIMALS */
        for(i = 0; i < A.lNumAnimals; i++)
        {
                SV ** svAnimal = av_fetch(avAnimals, i, FALSE);
                if(!SvOK(*svAnimal)) {
                   printf("Error - av_fetch animals array, %d returned bad sv\n", i);
                }
                HV * hvAnimal = (HV*)(SvRV(*svAnimal));

                setDouble(hvAnimal, "doubleField", A.animal[i].doubleField);
                setLong(hvAnimal, "longField", A.animal[i].longField);
        }

        RETVAL = 1;

  OUTPUT:
        RETVAL

  CLEANUP:
        Safefree(A.animal);
        Safefree(P.plant);

-----Original Message-----
From: Shinar, Tamar 
Sent: Monday, March 10, 2003 2:33 PM
To: [EMAIL PROTECTED]
Subject: HV to C struct


Hi,

I am trying to write an xs interface to an external library.  
My code takes two perl arrays, allocates and populates corresponding C structures, and 
passes them to the library routine.
The problem is that the program is unstable.  It will sometimes cause core dumps in 
the external library.  The library in itself is believed to be stable, so it seems to 
be something in the perl/C interface.  I use the following three functions to retrieve 
values from my perl objects in order to copy them into the C structures.
Does anyone see anything wrong here?

thank you,

Tamar
_______________________________________________________

char *
getString(HV * source, char * fieldName) 
{
  SV ** sv = hv_fetch(source, fieldName, strlen(fieldName), FALSE);
  if(!SvOK(*sv)) {
         printf("Error - hv_fetch %s returned bad sv\n", fieldName);
  }
  return SvPV(*sv, PL_na);
}

double
getDouble(HV * source, char * fieldName)
{
  SV ** sv = hv_fetch(source, fieldName, strlen(fieldName), FALSE);
  if(!SvOK(*sv)) {
         printf("Error - hv_fetch %s returned bad sv\n", fieldName);
  }
  return SvNV(*sv);
}

long
getLong(HV * source, char * fieldName)
{
  SV ** sv = hv_fetch(source, fieldName, strlen(fieldName), FALSE);
  if(!SvOK(*sv)) {
         printf("Error - hv_fetch %s returned bad sv\n", fieldName);
  }
  return SvIV(*sv);
}

Reply via email to