> 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);
}