Discussion:
Tied Hashes, XS and OMG, I'm over my head!
(too old to reply)
Justin Hammond
2007-07-21 05:16:16 UTC
Permalink
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
William Ahern
2007-07-21 05:54:39 UTC
Permalink
On Sat, Jul 21, 2007 at 01:16:16PM +0800, Justin Hammond wrote:
<snip>
Post by Justin Hammond
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
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)
In Perl you can never return an Array or Hash directly, only a reference to
such (unless you get into list coercion, but that's clearly not what you
want here). This goes for Perl or Perl XS. You can only return scalar values
(strings, integers, references, etc) from routines.

My XS is rusty, so I'll refrain from posting psuedo-code lest I confuse you.
Hopefully you get the idea.

I'm too tired/lazy to attempt a stab at your second question. Sorry ;)
Justin Hammond
2007-07-24 07:06:41 UTC
Permalink
Post by Justin Hammond
<snip>
Post by Justin Hammond
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
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)
In Perl you can never return an Array or Hash directly, only a
reference to
such (unless you get into list coercion, but that's clearly not what you
want here). This goes for Perl or Perl XS. You can only return
scalar values
(strings, integers, references, etc) from routines.
My XS is rusty, so I'll refrain from posting psuedo-code lest I confuse you.
Hopefully you get the idea.
I'm too tired/lazy to attempt a stab at your second question. Sorry ;)
Hi,
I figured out the FIRSTKEY, NEXTKEY issue and got that working
correctly now, but still got a problem with the STORE function.

I'm wondering if I have to use magic on all levels in a nested hash?

If I use DUMP on the different levels of the HASH, I see magic
applied to all variables upto the last one. eg:
Dump($hostserv) <- got magic
Dump($hostserv->{0}) <- got magic
Dump($hostserv->{0}->{nick}) <- No magic

In my XS code, I'm only applying magic to the $hostserv variable, and
not the nested hashs, but from reading other code, it seemed to be
"inherited". Any ideas?

Thanks
Justin Hammond
2007-07-24 05:29:49 UTC
Permalink
Post by Justin Hammond
<snip>
Post by Justin Hammond
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
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)
In Perl you can never return an Array or Hash directly, only a
reference to
such (unless you get into list coercion, but that's clearly not what you
want here). This goes for Perl or Perl XS. You can only return
scalar values
(strings, integers, references, etc) from routines.
My XS is rusty, so I'll refrain from posting psuedo-code lest I confuse you.
Hopefully you get the idea.
I'm too tired/lazy to attempt a stab at your second question. Sorry ;)
Hi,
I figured out the FIRSTKEY, NEXTKEY issue and got that working
correctly now, but still got a problem with the STORE function.

I'm wondering if I have to use magic on all levels in a nested hash?

If I use DUMP on the different levels of the HASH, I see magic
applied to all variables upto the last one. eg:
Dump($hostserv) <- got magic
Dump($hostserv->{0}) <- got magic
Dump($hostserv->{0}->{nick}) <- No magic

In my XS code, I'm only applying magic to the $hostserv variable, and
not the nested hashs, but from reading other code, it seemed to be
"inherited". Any ideas?

Thanks

Loading...