UPDATE:
This issue was caused by my ignorance of my Perl's pointer size (8 bytes in this case). Packing the pointer into an integer of the correct size "fixes" the issue I was experiencing. Thank you tye and ikegami for your help!
(It is obvious now in hindsight, but maybe the Perldocs for pack/unpack could be updated to mention the 'p/P' templates and Perl's pointer size?)
Good evening!
I am trying to more clearly learn how pack/unpack works with values returned from Win32::API, specifically pointers and how to dereference them. I have a small example program that calls a "cat" function in a "test.dll" that takes two strings and returns them concatenated together.
Setting the output parameter in the function template to char* works as expected:
#!/usr/bin/perl
use 5.018;
use strict;
use warnings;
use Win32::API;
use Data::Dumper;
$Win32::API::DEBUG = 1;
my $method = new Win32::API::More('test.dll', 'char* cat(char* a, char
+* b)');
if( !defined $method ) {
die "Can't import API [cat]: $^E\n";
}
my $return = $method->Call('my ', 'potato');
print Dumper $return; # prints 'my potato'
Setting the output parameter to int in the function template returns a valid pointer (I can peek at that memory address and see the concatenated string), and I can dereference it with various combinations of pack/unpack, but I do not know why some work:
#!/usr/bin/perl
use 5.018;
use strict;
use warnings;
use Win32::API;
use Data::Dumper;
$Win32::API::DEBUG = 1;
my $method = new Win32::API::More('test.dll', 'int cat(char* a, char*
+b)');
if( !defined $method ) {
die "Can't import API [cat]: $^E\n";
}
my $return = $method->Call('my ', 'potato');
print Dumper $return; # pointer address: 42952784
# works as expected: 'my potato'
my $x = unpack 'p', pack 'J', $return;
print Dumper $x;
# works as expected: 'my potato'
my $x = unpack 'p', pack 'Q', $return;
print Dumper $x;
# does not work as expected: undef
my $x = unpack 'p', pack 'I', $return;
print Dumper $x;
# does not work as expected: undef
my $x = unpack 'p', pack 'L', $return;
print Dumper $x;
# does not work as expected: undef
my $x = unpack 'p', pack 'N', $return;
print Dumper $x;
# Update: I made a typo in my original post.
# This (obviously) will not work on little-endian machines
#my $x = unpack 'p', pack 'N2', $return;
#print Dumper $x;
# works(??): 'my potato'
#my $x = unpack 'p', pack 'V2', $return;
#print Dumper $x;
# works(??): 'my potato'
my $x = unpack 'p', pack 'IN', $return;
print Dumper $x;
What exactly is going on with the different combinations of pack/unpack?
Perl info:
perl -v
This is perl 5, version 18, subversion 4 (v5.18.4) built for MSWin32-x
+64-multi-thread
USE_64_BIT_INT has been enabled as well.
Version 0.82 of Win32-API
Thank you for your time
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.