// Simple database-like module. // This shows how one can convert to and from C structures // from Perl5 array references. %module db %{ #include "db.h" %} // We use a typemap to define how we want to parse User records // Define how a User record is to be passed into a C function // This works for both "User" and "User *" %typemap(perl5,in) User * { static User temp; /* A temporary holding place */ AV *tempav; I32 len; SV **tv; char *login,*name,*home; /* Temporary variables */ if (!SvROK($source)) croak("$source is not a reference."); if (SvTYPE(SvRV($source)) != SVt_PVAV) croak("$source is not an array."); tempav = (AV*)SvRV($source); len = av_len(tempav); if (len != 4) croak("Invalid array size."); /* Now grab values out of the array */ tv = av_fetch(tempav,0,0); login = (char *) SvPV(*tv,PL_na); strncpy(temp.login,login,16); tv = av_fetch(tempav,1,0); temp.uid = (int) SvIV(*tv); tv = av_fetch(tempav,2,0); temp.gid = (int) SvIV(*tv); tv = av_fetch(tempav,3,0); name = (char *) SvPV(*tv,PL_na); strncpy(temp.name,name,32); tv = av_fetch(tempav,4,0); home = (char *) SvPV(*tv,PL_na); strncpy(temp.home,home,256); /* Set the User * pointer to our temporary structure */ $target = &temp; } // Describe how we want to return a user record %typemap(perl5,out) User * { AV *myav; SV **svs; if ($source) { svs = (SV **) malloc(5*sizeof(SV *)); svs[0] = sv_newmortal(); sv_setpv((SV*) svs[0],$source->login); svs[1] = sv_newmortal(); sv_setiv((SV*) svs[1],$source->uid); svs[2] = sv_newmortal(); sv_setiv((SV*) svs[2],$source->uid); svs[3] = sv_newmortal(); sv_setpv((SV*) svs[3],$source->name); svs[4] = sv_newmortal(); sv_setpv((SV*) svs[4],$source->home); myav = av_make(5,svs); free(svs); $target = newRV((SV *) myav); sv_2mortal($target); argvi++; } } extern void add_user(User u); extern void sort_users(); extern User *lookup_user(char *name); extern User *get_user(int index); extern int num_users();