String62 has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I am returning from an inline C function an array filled with references to hashes (see my code below). In this particular case, just for testing, I am returning 1 hash. In the perl code I am walking the array, and subsequently walking the hash. I am returning correctly the keys of the hash, but for whatever reason, getting at the key-value fails in the foreach loop of the hash. Tried everything, but currently to no avail. The uncommented line prints the keys. Uncommenting the second one doesn't produce the values. Tried hard and really wondering what's going on here. Could somebody have a look at this. Any help very much appreciated. Cheers,
.......... foreach my $key (sort keys %$href) { print "Key: ".$key."\n"; # print "Key: ".$key." => Value: ".$href->{$key}."\n"; } ..........
COMPLETE CODE: -------------
use Inline C; $array_ref = get_data(); print "Array ref: ".$array_ref."\n"; $href = $array_ref->[0]; print "Hash ref: ".$href."\n"; foreach my $key (sort keys %$href) { print "Key: ".$key." => Value: ".$value."\n"; # print "Key: ".$key." => Value: ".$href->{$key}."\n"; } __END__ __C__ SV* get_data() { SV * x; AV * results; I32 nr = 0; int i, n; results = (AV *)sv_2mortal((SV *)newAV()); for (n = 0; n <= nr; n++) { HV * rh; STRLEN l; rh = (HV *)sv_2mortal((SV *)newHV()); hv_store(rh, "mickey", 6, "mouse", 0); hv_store(rh, "donkey", 6, "kong", 0); av_push(results, newRV((SV * )rh)); } return newRV((SV*)results); }

Replies are listed 'Best First'.
Re: Inline C : dereferencing array of hash references returned from function
by syphilis (Archbishop) on Feb 16, 2011 at 04:59 UTC
    Couldn't get your code, or ikegami's to work for me ... not sure why. (Update: Nothing wrong with ikegami's code, of course. Looks to me that $value in the op's code bears no relation to the hashref that has been returned and therefore is undef.)

    The following *does* work for me, and should contain all you need to get your own code working:
    use Inline C => Config => BUILD_NOISY => 1; use Inline C; $arref = get_data(); print $arref, "\n"; print $arref->[0]->{mickey}, "\n"; print $arref->[0]->{donkey}, "\n"; __END__ __C__ SV* get_data() { AV * results; HV * rh = newHV(); results = newAV(); hv_store(rh, "mickey", 6, newSVpv("mouse", 0), 0); hv_store(rh, "donkey", 6, newSVpv("kong", 0), 0); av_push(results,newRV_noinc((SV*)rh)); return newRV_noinc((SV*)results); }
    Update: The 'BUILD_NOISY' config option that I've included in the above script ensures that you get the opportunity to see compiler warnings - which can be useful if a script does not behave as intended. It's a good idea to *always* have BUILD_NOISY switched on.

    Cheers,
    Rob
      Changed a little your code to print out the keys as well as the values. De-referencing the hash is now ok, see code below. Thanks to you and ikegami for being so responsive, it helped me on my way. PS: indeed BUILD NOISY option is very informative.
      use Inline C => Config => BUILD_NOISY => 1; use Inline C; $arref = get_data(); print $arref, "\n"; $href = $arref->[0]; foreach my $key (sort keys %$href) { # print "v1 Key: ", $key, " => Value: ", $arref->[0]->{$key}, " +\n"; print "v2 Key: ", $key, " => Value: ", $href->{$key}, "\n"; } __END__ __C__ SV* get_data() { AV * results; HV * rh = newHV(); results = newAV(); hv_store(rh, "mickey", 6, newSVpv("mouse", 0), 0); hv_store(rh, "donkey", 6, newSVpv("kong", 0), 0); av_push(results,newRV_noinc((SV*)rh)); return newRV_noinc((SV*)results); }
      Hi Rob, "Couldn't get your code", well here's the recipe, get a windows box (heheheh ;-)), with active state perl installed (mine is currently 5.10.0), ppm install mingw. At least this works for me. It also works for me with visual studio 2005. Made a copy of the vsvars32.bat file and added "perl.exe %1" as the last line in this file. Invoking perl scripts with this bat file works also fine, and uses MS's nmake instead of MinGW's dmake. Anyway, you can be sure I'll test out your code asap and come back to comment. Thank you very much for your reply ! Really appreciate, Bruno
        "Couldn't get your code to work", not "Couldn't get your code"
Re: Inline C : dereferencing array of hash references returned from function
by ikegami (Patriarch) on Feb 16, 2011 at 00:39 UTC

    I don't know if it addresses your question at all, but I see major errors.

    The only thing that should be mortal is the RV you return. Everything else is being referenced.

    The fourth argument of hv_store is documented to be an SV*. I don't see how what you have could even compile.

    SV* get_data() { AV * results; I32 nr = 0; int n; results = newAV(); for (n = 0; n <= nr; n++) { HV * rh = newHV(); { SV * val = newSVpv("mouse", 0); hv_store(rh, "mickey", 6, val, 0); } { SV * val = newSVpv("kong", 0); hv_store(rh, "donkey", 6, val, 0); } av_push(results, newRV_noinc((SV*)rh)); } return newRV_noinc((SV*)results); }

    Untested.

    The usage of newRV is not documented, so I used newRV_noinc.

    Your loop is completely useless, but I left it in since I figure you would eventually use it.

      First of all, thank you very much having a look at it. I am quite new to inline c, xs, I am still on the steep curve leraning the perl c api. As you mention the loop is completely useless, but this is on purpose. I want to return more hashes later, just 1 suffices for now. For the compilateion, it compiles fine with active state perl 5.10 with dmake (after installing minwg ppm module) as wel as with nmake (with visual studio environment). I will test out your suggestions above. Many Thanks,
      Hello Ikegami, Indeed, the 4th argument should be a SV*, naïve try from me, but yep I'm an inline - xs beginner. The code works just by changing :
      ..... hv_store(rh, "donkey", 6, "kong", 0); .....
      to :
      ..... hv_store(rh, "donkey", 6, newSVpv("kong", 0), 0); .....
      The key-value pairs are now printed out as one expects. As pointed out by you it's maybe better indeed to use the documented newRV_noinc function. Curious to sort out the differences between the two. Many thanks for your time, Cheers, Bruno

        Curious to sort out the differences between the two.

        Not much...

        #define newRV_inc(sv) newRV(sv)

        "newRV_inc is the official function name to use now." according to a comment.