Justin Hammond
2007-07-21 05:16:16 UTC
Hi All,
I'm very much new to Perl XS and embedding perl interpreters in my
programs. (and a complete newbie to the perl language itself!)
Anyway, I'm trying to expose a bunch of C structures stored in a C
hash to perl. So far, I've pretty much got the new, FETCH, EXISTS,
FIRSTKEY and NEXTKEY functions written in my XS file, but I'm hitting
a few problems and banging my head around the STORE function. I've
got a few questions that I hope you all don't mind helping me out with:
For FIRSTKEY and NEXTKEY, I'm a little confused what I should return
back. Do I return the actual HASH, or do I return the key name for
the value?
Currently, I'm returning the HASH, and when doing the following code
in perl, I get the following output:
my $hostserv = new NeoStats::NV("HostServ");
while ( my ($key, $value) = each(%$hostserv)) {
NeoStats::debug("Hostserv Key => $value");
while ( my ($key1, $value1) = each(%$key)) {
NeoStats::debug("HS: $key: $key1 => $value1");
}
}
WARNING Test - Hostserv Key => HASH(0x1a702c0)
WARNING Test - HS: HASH(0x1a68f18): passwd => asasasd
<snip>
As you can see, the "Key is actual a HASH". How do I get the actual
key used rather than this reference (note that FETCH works fine though)
for my second issue with Store, some background. I'm representing my
c Structure as a perl hash, and these structures are stored in either
a C hash, or doubly linked lists. so for example in perl if I do:
$var->{key}->{field} it means I want to retrieve the structure stored
with the "key" and the field from that structure. eg:
typedef struct {
char *field;
char *field1;
}
In my FETCH function I do the following:
hash = (HV*)SvRV(self);
mg = mg_find(SvRV(self),'~');
if(!mg) { croak("lost ~ magic"); }
/* this is the nv_hash we are point at */
nv = (nv_list *)SvIV(mg->mg_obj);
/* get the "key" they want */
k = SvPV(key, klen);
/* search for the key */
data = hnode_find((hash_t *)nv->data, k);
RETVAL = (HV *)perl_encode_namedvars(nv, data);
perl_encode_namedvars does the following:
HV *perl_encode_namedvars(nv_list *nv, void *data) {
HV *ret;
int i =0;
ret = newHV();
while (nv->format[i].fldname != NULL) {
switch(nv->format[i].type) {
case NV_PSTR:
case NV_STR:
hv_store(ret, nv->format[i].fldname,
strlen(nv->format[i].fldname),
newSVpv(nv_gf_string(data,
nv, i), strlen(nv_gf_string(data, nv, i))), 0);
break;
case NV_INT:
case NV_LONG:
hv_store(ret, nv->format[i].fldname,
strlen(nv->format[i].fldname),
newSViv(nv_gf_int(data, nv,
i)), 0);
break;
case NV_VOID:
case NV_PSTRA:
break;
}
i++;
}
return ret;
}
So far, so good, I can get a copy of my C structures in Perl. But
when I want to modify a field in perl, my STORE function never gets
called. eg:
$hostserv->{key}->{field} = "test"
Nothing :(
But if I do:
my $newvar;
$newvar->{field} = "test";
$hostserv->{key} = $newvar;
it works like a dream.
So, can anybody shed any light on what I'm doing wrong?
(I've posted some condensed code here, if you want to see the actual
code I'm working on, its here: http://svn.neostats.net/cgi-bin/
viewvc.cgi/NeoStats/trunk/src/NV.xs?revision=3127&view=markup)
(btw, I've dug though all the examples, such as solaris::kstats etc I
could find, and think with reading the doco, and browsing these
mailing lists, I'm probably doing something stupid, and have confused
myself beyond doubt!)
Thanks
Justin
I'm very much new to Perl XS and embedding perl interpreters in my
programs. (and a complete newbie to the perl language itself!)
Anyway, I'm trying to expose a bunch of C structures stored in a C
hash to perl. So far, I've pretty much got the new, FETCH, EXISTS,
FIRSTKEY and NEXTKEY functions written in my XS file, but I'm hitting
a few problems and banging my head around the STORE function. I've
got a few questions that I hope you all don't mind helping me out with:
For FIRSTKEY and NEXTKEY, I'm a little confused what I should return
back. Do I return the actual HASH, or do I return the key name for
the value?
Currently, I'm returning the HASH, and when doing the following code
in perl, I get the following output:
my $hostserv = new NeoStats::NV("HostServ");
while ( my ($key, $value) = each(%$hostserv)) {
NeoStats::debug("Hostserv Key => $value");
while ( my ($key1, $value1) = each(%$key)) {
NeoStats::debug("HS: $key: $key1 => $value1");
}
}
WARNING Test - Hostserv Key => HASH(0x1a702c0)
WARNING Test - HS: HASH(0x1a68f18): passwd => asasasd
<snip>
As you can see, the "Key is actual a HASH". How do I get the actual
key used rather than this reference (note that FETCH works fine though)
for my second issue with Store, some background. I'm representing my
c Structure as a perl hash, and these structures are stored in either
a C hash, or doubly linked lists. so for example in perl if I do:
$var->{key}->{field} it means I want to retrieve the structure stored
with the "key" and the field from that structure. eg:
typedef struct {
char *field;
char *field1;
}
In my FETCH function I do the following:
hash = (HV*)SvRV(self);
mg = mg_find(SvRV(self),'~');
if(!mg) { croak("lost ~ magic"); }
/* this is the nv_hash we are point at */
nv = (nv_list *)SvIV(mg->mg_obj);
/* get the "key" they want */
k = SvPV(key, klen);
/* search for the key */
data = hnode_find((hash_t *)nv->data, k);
RETVAL = (HV *)perl_encode_namedvars(nv, data);
perl_encode_namedvars does the following:
HV *perl_encode_namedvars(nv_list *nv, void *data) {
HV *ret;
int i =0;
ret = newHV();
while (nv->format[i].fldname != NULL) {
switch(nv->format[i].type) {
case NV_PSTR:
case NV_STR:
hv_store(ret, nv->format[i].fldname,
strlen(nv->format[i].fldname),
newSVpv(nv_gf_string(data,
nv, i), strlen(nv_gf_string(data, nv, i))), 0);
break;
case NV_INT:
case NV_LONG:
hv_store(ret, nv->format[i].fldname,
strlen(nv->format[i].fldname),
newSViv(nv_gf_int(data, nv,
i)), 0);
break;
case NV_VOID:
case NV_PSTRA:
break;
}
i++;
}
return ret;
}
So far, so good, I can get a copy of my C structures in Perl. But
when I want to modify a field in perl, my STORE function never gets
called. eg:
$hostserv->{key}->{field} = "test"
Nothing :(
But if I do:
my $newvar;
$newvar->{field} = "test";
$hostserv->{key} = $newvar;
it works like a dream.
So, can anybody shed any light on what I'm doing wrong?
(I've posted some condensed code here, if you want to see the actual
code I'm working on, its here: http://svn.neostats.net/cgi-bin/
viewvc.cgi/NeoStats/trunk/src/NV.xs?revision=3127&view=markup)
(btw, I've dug though all the examples, such as solaris::kstats etc I
could find, and think with reading the doco, and browsing these
mailing lists, I'm probably doing something stupid, and have confused
myself beyond doubt!)
Thanks
Justin