Hi Guys
Suppose I do something like this:
void make_struct{HV* hash_ref} { hv_store(hash_ref, "key",3, newRV_noinc((SV*)arr_ref = newAV()), 0); av_store(arr_ref, 1, newRV_noinc((SV*)hash2_ref = newHV())); hv_store(hash2_ref, "test", 4, 33); }
And then in perl if I did this:
my %testhash = (); make_struct(\%testhash); print $testhash{key}[1]{test}
And this would print 33 right?
use warnings; use strict; #use Devel::Peek; # To Dump() the vars. #use Devel::Leak; # To get a count of "things".
use Inline C => Config => BUILD_NOISY => 1;
use Inline C => <<'EOC';
void make_struct(HV * hash_ref) { SV ** ret; SV * arr_ref, * hash2_ref;
arr_ref = NEWSV(0,0); // alternatively newSV(0) hash2_ref = NEWSV(0,0); // alternatively newSV(0)
arr_ref = newRV_noinc(arr_ref); hash2_ref = newRV_noinc(hash2_ref);
(AV*)SvRV(arr_ref) = newAV(); (HV*)SvRV(hash2_ref) = newHV();
SvREFCNT_inc(arr_ref); ret = hv_store(hash_ref, "key", 3, arr_ref, 0); if(ret == NULL) { SvREFCNT_dec(arr_ref); croak("1: hv_store() failed\n"); }
SvREFCNT_inc(hash2_ref); ret = av_store((AV*)SvRV(arr_ref), 1, hash2_ref); if(ret == NULL) { SvREFCNT_dec(hash2_ref); croak("av_store() failed\n"); }
ret = hv_store((HV*)SvRV(hash2_ref), "test", 4, newSViv(33), 0); if(ret == NULL) croak("2: hv_store() failed \n"); }
void make_struct2(HV * hash_ref, SV * arr_ref, SV * hash2_ref) { SV ** ret;
SvREFCNT_inc(arr_ref); ret = hv_store(hash_ref, "key", 3, arr_ref, 0); if(ret == NULL) { SvREFCNT_dec(arr_ref); croak("1: hv_store() failed\n"); }
SvREFCNT_inc(hash2_ref); ret = av_store((AV*)SvRV(arr_ref), 1, hash2_ref); if(ret == NULL) { SvREFCNT_dec(hash2_ref); croak("av_store() failed\n"); }
ret = hv_store((HV*)SvRV(hash2_ref), "test", 4, newSViv(33), 0); if(ret == NULL) croak("2: hv_store() failed \n"); }
EOC
# my @arr = (); # my %testhash2 = (); my %testhash = ();
# my $lh; # my $count = Devel::Leak::NoteSV($lh);
make_struct(\%testhash); # Alternatively (do one or the other, but not both): # make_struct2(\%testhash, [EMAIL PROTECTED], \%testhash2);
# my $count2 = Devel::Leak::CheckSV($lh);
# print "Final Count = ", $count2, "\n"; # Gives the same value for both make_struct() # and make_struct(2) - which is good news.
# print "Count has increased by ", # $count2 - $count, " things\n";
print $testhash{key}[1]{test}, "\n";
# The following 2 Dumps should be the same, # except for the addresses. # Dump($testhash{key}[1]{test}); # print "#########\n"; # our $x = 33; # Dump($x);
__END__
(If you remove all of the commented-out perl code in my script, you'll end up with the same perl code that you posted).
There's 2 solutions there - make_struct() and make_struct2().
make_struct2() is a little easier to follow because it has perl create arr_ref and hash2_ref for the inline function.
One problem (for me, at least) is that if you want to hv_store() HV*a in HV*b, then you have to make HV*a into an SV* (because hv_store() requires that its 4th argument be an SV*). Similarly, if you want to hv_store an AV*, then you need to make it, also, into an SV*. Now ... I don't know how to make a HV*/AV* into an SV* (perhaps someone else can offer some advice here) - which is why both 'make_struct()' and 'make_struct2()' have arr_ref and hash2_ref passed/created as SV*'s.
Then, whenever hash2_ref has to be a HV*, it's easy to cast it to one using (HV*)SvRV(hash2_ref). And the same goes for arr_ref.
I don't really know the difference between newRV_noinc and newRV_inc and I've been unable to detect a difference between them (as regards the above code). I assume that, since noinc works ok, then it's the right one to use.
I'm also a little concerned that, perhaps, make_struct() does things a little stupidly ... or perhaps even sinfully. I *think* it's ok, but I'd be more confident about it if it had been written by someone a little more expert than I :-)
Anyway, that's the best I could come up with. Hope it helps.
Cheers, Rob