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: do...@cpan.org Status: open Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=74578 >
On Fri Feb 03 20:51:26 2012, rur...@x-ray.at 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) {