我在perl中构建二进制数据。 该二进制数据基于C结构,用于32位和64位,大端和小端系统。 diffucult部分是FORMAT结构中的位域。这在小/大端架构的内存中有不同的布局。
我目前正在制作像这样的位域:
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
但是我希望以单包形式提供上述内容(因此不会调用包两次,并且结果然后打印它。)
最终我想一次打印整个FORMAT记录。
pack("Q>3L>L>", X, Y, Z, ???, 0) #64bit big endian
我有大约500k FORMAT记录需要写出来,并且每次记录多次调用pack()太昂贵了。
答案 0 :(得分:1)
您可以使用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))