perl: 构建 big/little endian bigfields 并用单个包输出它们
perl: build big/little endian bigfields and output them with a single pack
我正在用 perl 构建二进制数据。
此二进制数据基于 C 结构,用于 32 位和 64 位、大端和小端系统。
困难的部分是 FORMAT 结构中的位域。在 little/big endian 架构中,这在内存中的布局不同。
我目前正在制作这样的位域:
struct FORMAT
{
void * X,
void * Y,
void * Z,
unsigned int size : 26;
unsigned int type : 6;
<4 byte padding on 64bit targets>
}
my $size = 0x3C;
my $type = 0x05;
=> big endian
print pack("L>", $size << 6) | pack("L>", $type); # 00 00 0f 05
=> little endian
print pack("L<", $size) | pack("L<", $type << 26); # 3c 00 00 14
但我希望将上面的内容以单个包的格式呈现,(因此不会调用 pack 两次,然后将结果或结果打印出来。)
最终我想一次打印一整条 FORMAT 记录。
pack("Q>3L>L>", X, Y, Z, ???, 0) #64bit big endian
我有大约 50 万条 FORMAT 记录需要写出,并且为每条记录多次调用 pack() 成本太高。
你可以使用 XS。这将为您处理字节顺序和特定于编译器的对齐方式(填充)。
use strict;
use warnings;
use Inline C => <<'__EOC__';
typedef struct {
void* X;
void* Y;
void* Z;
unsigned int size: 26;
unsigned int type: 6;
} FORMAT;
SV* pack_FORMAT(UV X, UV Y, UV Z, unsigned int size, unsigned int type) {
FORMAT format;
format.X = INT2PTR(void*, X);
format.Y = INT2PTR(void*, Y);
format.Z = INT2PTR(void*, Z);
format.size = size;
format.type = type;
return newSVpvn(&format, sizeof(format));
}
__EOC__
my $size = 0x3C;
my $type = 0x05;
my $packed = pack_FORMAT(0, 0, 0, $size, $type);
printf("%v02X\n", $packed);
也就是说
pack("L>", $size << 6) | pack("L>", $type)
pack("L<", $size) | pack("L<", $type << 26)
可以写成
pack("L>", ($size << 6) | $type)
pack("L<", $size | ($type << 26))
我正在用 perl 构建二进制数据。 此二进制数据基于 C 结构,用于 32 位和 64 位、大端和小端系统。 困难的部分是 FORMAT 结构中的位域。在 little/big endian 架构中,这在内存中的布局不同。
我目前正在制作这样的位域:
struct FORMAT
{
void * X,
void * Y,
void * Z,
unsigned int size : 26;
unsigned int type : 6;
<4 byte padding on 64bit targets>
}
my $size = 0x3C;
my $type = 0x05;
=> big endian
print pack("L>", $size << 6) | pack("L>", $type); # 00 00 0f 05
=> little endian
print pack("L<", $size) | pack("L<", $type << 26); # 3c 00 00 14
但我希望将上面的内容以单个包的格式呈现,(因此不会调用 pack 两次,然后将结果或结果打印出来。)
最终我想一次打印一整条 FORMAT 记录。
pack("Q>3L>L>", X, Y, Z, ???, 0) #64bit big endian
我有大约 50 万条 FORMAT 记录需要写出,并且为每条记录多次调用 pack() 成本太高。
你可以使用 XS。这将为您处理字节顺序和特定于编译器的对齐方式(填充)。
use strict;
use warnings;
use Inline C => <<'__EOC__';
typedef struct {
void* X;
void* Y;
void* Z;
unsigned int size: 26;
unsigned int type: 6;
} FORMAT;
SV* pack_FORMAT(UV X, UV Y, UV Z, unsigned int size, unsigned int type) {
FORMAT format;
format.X = INT2PTR(void*, X);
format.Y = INT2PTR(void*, Y);
format.Z = INT2PTR(void*, Z);
format.size = size;
format.type = type;
return newSVpvn(&format, sizeof(format));
}
__EOC__
my $size = 0x3C;
my $type = 0x05;
my $packed = pack_FORMAT(0, 0, 0, $size, $type);
printf("%v02X\n", $packed);
也就是说
pack("L>", $size << 6) | pack("L>", $type)
pack("L<", $size) | pack("L<", $type << 26)
可以写成
pack("L>", ($size << 6) | $type)
pack("L<", $size | ($type << 26))