如何在 64 位 Perl 中解压缩(64 位)无符号长整数?

Posted

技术标签:

【中文标题】如何在 64 位 Perl 中解压缩(64 位)无符号长整数?【英文标题】:How to unpack (64-bit) unsigned long in 64-bit Perl? 【发布时间】:2011-03-30 15:35:01 【问题描述】:

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

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

还知道 php 在 bug 中有something similar(搜索“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(); 很多空字节沿着一些有意义的.. byteorder='12345678';

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

【问题讨论】:

在您的打包字符串上显示Data::Dumper->new($string)->Useqq(1)->Dump 的输出以及您期望的数字。也许 perl -V:byteorder 的输出 对不起,我的意思是print Data::Dumper...的输出 @ysth, VAR1 = "\210\23\0\0\0\0\0\0\210\23\0\0\0\0\0\0\177\0 \0\1\0\0\0\0\177\0\0\1\0\0\0\0W\273\@\37\0\0\0\0^\330u\0\0 \0\0\264\13\340u\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \16T\223M\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - 哇,太多的\0,检查。也许my $string 声明不适合某处的返回类型。 您是否尝试过解压缩脚本中编码的标量常量?一旦你开始工作,试试管道...... @drewk,不,我只是可以同时运行所有三个程序,(Perl 版本目前不起作用,除非我能摆脱这个解包问题)并且它可以快速重新启动.. 不是时候单元测试:) 【参考方案1】:

如果您有 64 位 Perl,则使用 the template 中的 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);

【讨论】:

两者都不能正常工作;源值 = 563026057,在辅助 C 应用程序中解压相同,native_to_int64 = 2418178501610831872,net_to_int64 = 2300088097【参考方案2】:

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

【讨论】:

以上是关于如何在 64 位 Perl 中解压缩(64 位)无符号长整数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Perl 中解压缩双精度值?

使用 Perl64 在 Windows 7(64 位)上构建 BerkeleyDB 时出现编译/链接错误

使用 Ruby 从二进制字符串中解包一点

使用 32 位无符号整数乘以 64 位数字的算法

PHP:从二进制数据流中解压缩32位整数

使用 AVX512 将压缩 64 位整数转换为带符号饱和的压缩 8 位整数