Sun Feb 05 14:10:04 2012: Request 74578 was acted upon.
Transaction: Correspondence added by DOUGW
Queue: Win32-API
Subject: Win32::API::Struct alignment wrong
Broken in: 0.64
Severity: Normal
Owner: Nobody
Requestors: [email protected]
Status: open
Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=74578 >
On Fri Feb 03 20:51:26 2012, [email protected] wrote:
> Patch looks good. Aldo wanted to have that repeat bit fixed for a long
time.
> Thanks.
>
> Now if you can repro the w64 align problem and send the output with
> debugging info, please?
Like I said before, I don't think 64-bit had anything to do with this
bug, as I was using a 32-bit perl and dll. I've been reading up on Win32
alignment and finally completely understand what needs to be done. My
test structure was suppose to start off with a char[10] and I thought it
was just a typo in the docs...now I see that it should have "xx" after
it in the pack/unpack. Attached is an updated patch, which correctly
fixes the repeat logic, and also I believe fixes the alignment of the
elements in the Struct (on closer look, the repeat logic is why the
alignments were wrong). It looks good just from calling getPack and
getUnpack. I'll test it with the actual dll on Monday.
--- Struct.pm 2012-02-03 15:39:35 -0800
+++ Struct.pm 2012-02-03 15:52:38 -0800
@@ -200,9 +200,10 @@
$packing .= $subpacking;
$packed_size += $subpacksize;
} else {
+ my $repeat = 1;
if($type =~ /\w\*(\d+)/) {
- my $size = $1;
- $type = "a$size";
+ $repeat = $1;
+ $type = "a$repeat";
}
DEBUG "(PM)Struct::getPack($self->{__typedef__}) ++ $type\n";
@@ -215,9 +216,9 @@
}
push(@recipients, $self);
$type_size = Win32::API::Type::sizeof($orig);
- $type_align = (($packed_size + $type_size) % $type_size);
+ $type_align = (($packed_size + $type_size) % $type_size);
$packing .= "x" x $type_align . $type;
- $packed_size += $type_size + $type_align;
+ $packed_size += ($type_size*$repeat) + $type_align;
}
}
@@ -253,32 +254,33 @@
foreach my $member (@{ $self->{typedef} }) {
($name, $type, $orig) = @$member;
if($type eq '>') {
- my($subpacking, @subitems, $subpacksize) =
$self->{$name}->getUnpack();
+ my($subpacking, $subpacksize, @subitems) =
$self->{$name}->getUnpack();
DEBUG "(PM)Struct::getUnpack($self->{__typedef__}) ++
$subpacking\n";
$packing .= $subpacking;
$packed_size += $subpacksize;
push(@items, @subitems);
} else {
+ my $repeat = 1;
if($type =~ /\w\*(\d+)/) {
- my $size = $1;
- $type = "Z$size";
+ $repeat = $1;
+ $type = "Z$repeat";
}
DEBUG "(PM)Struct::getUnpack($self->{__typedef__}) ++ $type\n";
$type_size = Win32::API::Type::sizeof($orig);
- $type_align = (($packed_size + $type_size) % $type_size);
+ $type_align = (($packed_size + $type_size) % $type_size);
$packing .= "x" x $type_align . $type;
- $packed_size += $type_size + $type_align;
+ $packed_size += ( $type_size * $repeat ) + $type_align;
push(@items, $name);
}
}
DEBUG "(PM)Struct::getUnpack($self->{__typedef__}): unpack($packing,
@items)\n";
- return($packing, @items, $packed_size);
+ return($packing, $packed_size, @items);
}
sub Unpack {
my $self = shift;
- my($packing, @items) = $self->getUnpack();
+ my($packing, undef, @items) = $self->getUnpack();
my @itemvalue = unpack($packing, $self->{buffer});
DEBUG "(PM)Struct::Unpack: unpack($packing, buffer) = @itemvalue\n";
foreach my $i (0..$#items) {