4

我正在尝试解压缩通过 SysV::IPC 从 C 程序传递到 Perl 脚本的无符号长值。

已知该值是正确的(我做了一个测试,将相同的值发送到两个队列中,一个由 Perl 读取,第二个由 C 应用程序读取),并且所有前面的值都被正确读取(使用q而不是i!使用 64位整数)。

还知道 PHP 在 bug 中有类似的东西(搜索“unsigned long on 64 bit machines”)(似乎类似: Pack / unpack a 64-bit int on 64-bit architecture in PHP

到目前为止测试的参数:

  • ..Q(=某个大于预期的值)
  • ..L (= 0)
  • ..L!(=大值)
  • ..l (= 0)
  • ..l!(=大值)
  • ..lN!( = 0)
  • ..N,..N!( = 0)

use bigint; use bignum;- 没有效果。

细节:

  • sizeof(unsigned long)= 8;
  • Data::Dumper->new([$thatstring])->Useqq(1)->Dump();很多空字节沿着一些有意义的..
  • 字节序='12345678';

解决方案: -x4Q填充四个字节。

4

2 回答 2

3

如果您有 64 位 Perl,则Q模板中使用解包开箱即用:

The TEMPLATE is a sequence of characters that give the order
and type of values, as follows:

 ...

 q   A signed quad (64-bit) value.
 Q   An unsigned quad value.
       (Quads are available only if your system supports 64-bit
        integer values _and_ if Perl has been compiled to support those.
        Causes a fatal error otherwise.)

要获得更强大的解决方案,请将值解压缩为 8 字节字符串并使用Math::Int64模块将其转换为整数:

use Math::Int64 qw( :native_if_available int64 );

...

$string_value = unpack("A8", $longint_from_the_C_program);

# one of these two functions will work, depending on your system's endian-ness
$int_value = Math::Int64::native_to_int64($string_value);
$int_value = Math::Int64::net_to_int64($string_value);
于 2011-03-30T15:46:45.363 回答
1

解决方案很简单:x4Q在实际值之前添加跳过四个字节;需要更直观地考虑填充/对齐..

于 2011-03-30T18:03:36.370 回答