Nitin Madnani wrote:
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



Reply via email to