9

Possible Duplicate:
How can I convert the stringified version of array reference to actual array reference in Perl?

I have "SCALAR(0x8ec3a94)" as a literal string. Can I force Perl to turn this into a reference and then follow it?

IE, tell Perl: "look in memory location 0x8ec3a94, and treat whatever's there as a scalar"?

Related to: Perl: Unwrapping list inside-out doesn't work?

And yes, I realize this is a horrible thing to do.

Community
  • 1
  • 1
  • Related: http://stackoverflow.com/questions/1671281/how-can-i-convert-the-stringified-version-of-array-reference-to-actual-array-refe. Not strictly a dupe since that one was about ARRAYs. – Andy Apr 22 '11 at 21:59
  • 1
    No, a reference is not a pointer. How did it become a string in the first place? That's where the bug is. – shawnhcorey Apr 23 '11 at 12:47
  • @shawnhcorey, no it is not a pointer, but it contains the same information, see my answer – Joel Berger Apr 23 '11 at 14:33
  • No, a reference is not a pointer. If you treat as one, you'll create a whole bunch of extra work which nobody will understand and can't be maintained. And my question still remains: How did it become a scalar in the first place? That's where the OP made the error. – shawnhcorey Apr 23 '11 at 15:11
  • `And yes, I realize this is a horrible thing to do.` I'm taking the OP at his word. Let him continue down this path of darkness, so long as he promises NEVER to release any of this malice upon the world. – Joel Berger Apr 23 '11 at 15:20
  • I'm still wondering why he wants to do this. I've been using Perl since version 4 and only once in the entire time did I have to convert a reference to a string and that was to compare two to see if they were equal. There simply no need to do this. – shawnhcorey Apr 23 '11 at 17:06

2 Answers2

3

From the link given by Andy, try the Inline::C approach. You will want to use SV* rather than AV*, but it should work.

I have mocked up an example, extending the method shown in that link. With my limited knowledge of C I think I have prevented a Segfault when the reference no longer points to anything (test by un-commenting the inner braces, allowing $text to fall out of scope). Because I use newRV_inc in the C section, the reference count for $text is incremented. Therefore if $text falls out of scope, but its found reference ($recovered_ref) still exists, the value is still available, as expected (test by un-commenting the outer braces).

This method would seem to work for any type of reference. Not sure about objects, give it a go if you want. For more info perldoc Inline::C will help, but you will need to read perldoc perlguts and possibly even perldoc perlapi to continue down this path.

#!/usr/bin/perl

use strict;
use warnings;

use Inline 'C';

my $stringified_ref_text;
my $stringified_ref_array;
my $recovered_ref_text;
my $recovered_ref_array;

#{
  #{
    my $text = "Hello World";
    my @array = qw"Hello World!";

    $stringified_ref_text = \$text . "";
    $stringified_ref_array = \@array . "";

    print $stringified_ref_text . "\n";
    print $stringified_ref_array . "\n";
  #}

  $recovered_ref_text = recover_ref($stringified_ref_text);
  $recovered_ref_array = recover_ref($stringified_ref_array);
#}

print $$recovered_ref_text . "\n";
print "$_\n" for @$recovered_ref_array;

sub recover_ref {

  my $input = shift;

  my $addr;
  if ($input =~ /0x(\w+)/) {
    $addr = hex($1);
  } else {
    warn "Could not find an address";
    return undef;
  }
  my $ref = _recover_ref($addr) or undef;

  return $ref;
}

__DATA__
__C__

SV* _recover_ref(int address) { 
  if (address) 
    return newRV_inc((SV*) address);

  return 0;
}
Community
  • 1
  • 1
Joel Berger
  • 20,180
  • 5
  • 49
  • 104
  • By default, StackOverflow shows answers sorted by score, then settles ties (apparently) randomly. This means that the link you're referring to may appear below your answer or (in questions with more activity) appear several places above you with other links in between. So please don't refer to it as "the link above" if you want people to know which link you mean. – Dave Sherohman Apr 23 '11 at 07:14
  • @Dave, its the same link that I have post, only mine points to a specific answer in within. Should I have posted two links to the same question? This should do. – Joel Berger Apr 23 '11 at 13:24
  • 1
    I have been waiting for a simple reason to learn to make and package an XS module for CPAN (I only just released my first pure-Perl module a few days ago). Is this something that people would want on CPAN? It would give me a reason to attempt it. – Joel Berger Apr 23 '11 at 14:32
  • @Joel: Yes. Things like Acme::* are welcomed on CPAN. This could even be useful. – Tim Apr 23 '11 at 14:47
  • 1
    @Tim, thanks for the encouragement, look for Acme::RecoverReference, coming soon to a CPAN mirror near you – Joel Berger Apr 23 '11 at 15:09
  • Save yourself the trouble. It's already available as `unsmash_*` from [`Devel::Pointer::PP`](http://p3rl.org/Devel::Pointer::PP). – daxim Apr 23 '11 at 15:56
  • @daxim, true enough, oh well, I'll keep looking for the next idea. I have a big module in the pipe (linkages/driver for a scientific camera) and I have been hoping to find something small to try before doing that one. So far that one is in `Inline::C` because I am still bad at XS. For the life of me though, I can't figure out distributing `Inline::C` code in a way that seems natural to me. – Joel Berger Apr 23 '11 at 16:06
  • @Joel: The new version ("the link given by Andy") is good. I wasn't saying that you needed to add a duplicate link (although that wouldn't be bad...), just that you shouldn't call it "the link above" because you don't know what will be "above" for the reader, which can cause people to misunderstand which you meant - I, for example, thought you were talking about Greg's link to Tie::RefHash. – Dave Sherohman Apr 24 '11 at 05:55
2

The closest you can get is with Tie::RefHash. The poor man's version stuffs references in a hash

$registry{"$ref"} = $ref;

and then pulls it out later

print ${ $registry{"SCALAR(0x8ec3a94)"} }, "\n";

This approach has lots of drawbacks. Why do you want to do it this way?

Greg Bacon
  • 134,834
  • 32
  • 188
  • 245
  • I'm trying to parse something "inside out", starting with the innermost reference and working my way out. –  Apr 22 '11 at 22:16