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

Hello Monks,

I'm looking for nicer way, in pure Perl and standard library preferably, to get the address location of the actual data held by an SV.

I've implemented this ugly, regex-based hack below and it works, $ptr holds the actual address... but is there a better way?.

 use Data::Peek;
 my $buf = "hello world";
 my $dd = DDump( $buf );  # similar to Devel::Peek::Dump, but stringified
 my ($ptr) = $dd =~ /PV = (\S+)/; 
 $ptr = hex $ptr;  # $ptr had a string like "0x78ad928efff"

 use Devel::PeekPoke;
 print peek( $ptr, 4 );  # prints "hell", so it worked
Basically what I did was to capture the "PV = (...)" value out of the string with a regex. Here are the contents of the Devel::Peek::Dump():

SV = PV(0x7fea785135c0) at 0x7fea785264f0 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) PV = 0x7fea70219200 "hello world"\0 CUR = 11 LEN = 16

In case you are curious, the reason for getting the address is due to the need to call an external (to perl) system that wants mem address and length of the byte sequence, not to use peek()/poke() or any other Perl code hack.

Maybe the solution is to bless $buf into B::SV, then call one of its methods? Like I said, I want to avoid XS, C or hopefully any outside dependencies.

Replies are listed 'Best First'.
Re: Getting the PV pointer from a SV (pack 'p')
by BrowserUk (Patriarch) on Mar 09, 2016 at 12:10 UTC

    Use pack 'p'

    use Devel::Peek;; $s = 'Hello, world!';; Dump $s;; SV = PV(0x25c0b0) at 0x3d71b48 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x3d5e908 "Hello, world!"\0 CUR = 13 LEN = 16 print unpack 'V', pack 'p', $s;; 64350472 printf "%x\n", unpack 'V', pack 'p', $s;; 3d5e908

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Getting the PV pointer from a SV
by ikegami (Patriarch) on Mar 09, 2016 at 13:33 UTC

    This version also support 64-bit versions of Perl.

    $ perl -E' use Config qw( %Config ); my $ptr_size = $Config{ptrsize}; my $ptr_format = $ptr_size == 4 ? "L" : $ptr_size == 8 ? "Q" : die("Unrecognized pointer size"); my $s = "abc"; my $ptr = unpack($ptr_format, pack("p", $s)); say sprintf "0x%x", $ptr; use Devel::Peek; Dump($s); ' 0x1766c40 SV = PV(0x174dcf0) at 0x176d958 REFCNT = 1 FLAGS = (PADMY,POK,pPOK) PV = 0x1766c40 "abc"\0 CUR = 3 LEN = 16

    You should call utf8::upgrade or utf8::downgrade first to control the storage format of the string.

      Awesome, thanks for the 32/64-bit portability code.

      Pack/unpack "p" and "P" is such a mysterious template code to me... I wonder if Devel::PeekPoke::peek( ptr, len ) could be written also with pack/unpack... I wouldn't know where to put the length though, maybe in the template somewhere appended to the letter 'p'.

        Not only can it be done, that's exactly what Devel::PeekPoke::PP does.

        $ perl -E' use Config qw( %Config ); my $ptr_size = $Config{ptrsize}; my $ptr_format = $ptr_size == 4 ? "L" : $ptr_size == 8 ? "Q" : die("Unrecognized pointer size"); sub pv { unpack($ptr_format, pack("p", $_[0])) } sub peek { unpack('P'.$_[1], pack($ptr_format, $_[0])) } my $s = "abcdef"; my $ptr = pv($s); say peek($ptr+1, 4); ' bcde