The size of a pointer varies between different builds of Perl (even on the same system). The size of a pointer (in bytes) is available from

perl -V:ptrsize
and
perl -E"use Config qw( %Config ); say $Config{ptrsize};"

There is no pack format that's guaranteed to always produces exactly the size of a pointer on all systems. That means you need to determine the correct format from the aforementioned variable if you want a portable solution:

use Config qw( %Config ); my $ptr_size = $Config{ptrsize}; my $ptr_format = $ptr_size == 8 ? 'Q' : $ptr_size == 4 ? 'L' : die("Unrecognized pointer size"); my $s = unpack 'p', pack $ptr_format, $addr;

You have a pointer size of 8 bytes, so "Q" is the appropriate format for you.


To my knowledge, Windows only runs on little-endian systems. On a little-endian system, if you use an integer type that's too large, you'll simply add trailing zeros that will be ignored by unpack 'p'.

>perl -wE"say unpack 'p', pack('P', 'abc')" abc >perl -wE"say unpack 'p', pack('P', 'abc').qq{\0\0\0\0\0\0\0\0}" abc

As such, you can safely use "J" on such a system since the IV and UV types are guaranteed to be large enough to hold a pointer.

my $s = unpack 'p', pack 'J', $addr;

Some types should be avoided since they have unpredictable size: "I".

Some types should be avoided since they don't necessarily use native byte order: "N", "n", "V", "v".


# works(??): 'my potato' my $x = unpack 'p', pack 'N2', $return; print Dumper $x;

huh??? Aren't you on an x86 machine? That's a little-endian machine. On a little-endian system such as yours, "J" and "N2" will give different result, so they can't possibly both work.

>perl -wE"say sprintf '%vX', pack 'J', 0x0000000012345678" 78.56.34.12.0.0.0.0
>perl -wE"say sprintf '%vX', pack 'N2', 0x0000000012345678" 12.34.56.78.0.0.0.0

# works(??): 'my potato' my $x = unpack 'p', pack 'IN', $return; print Dumper $x;

You got lucky there.

>perl -wE"say sprintf '%vX', pack 'J', 42952784" 50.68.8F.2.0.0.0.0 >perl -wE"say sprintf '%vX', pack 'IN', 42952784" 50.68.8F.2.0.0.0.0

But it would have failed for larger addresses since your "I" only produces 4 bytes.

>perl -wE"say sprintf '%vX', pack 'J', 0x0123456789ABCDEF" EF.CD.AB.89.67.45.23.1 >perl -wE"say sprintf '%vX', pack 'IN', 0x0123456789ABCDEF" EF.CD.AB.89.0.0.0.0

When packing, there's no difference between corresponding signed and unsigned integer formats. I only mentioned unsigned pack formats above, but everything I said applies to the signed formats too.


In reply to Re: Dereferencing a pointer returned from Win32::API with unpack 'p' by ikegami
in thread [SOLVED] Dereferencing a pointer returned from Win32::API with unpack 'p' by ateague

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.