使用Device::BlinkyTape::SimulationPort触发unpack 'x'报错如何解决
报错原因
这个报错触发自Perl的unpack函数:当unpack模板中使用x(跳过字节)修饰符时,传入的待解析字符串长度短于模板要求的最小长度,就会抛出该错误。
你遇到的场景是Device::BlinkyTape::SimulationPort模块在调用show()方法时,待解析的像素缓冲区长度小于灯带总像素需要的字节数,导致模板解析越界。触发的原因有两个:
- 你的测试代码中存在只发送单个像素就调用
show()的逻辑,而BlinkyTape默认灯带长度为60个像素,每次show()前需要发送满60个像素的RGB数据(共180字节),单次发送单个像素只会写入3字节到缓冲区,长度不足导致解析失败。 - 旧版本的
Device::BlinkyTape::SimulationPort模块没有做缓冲区长度兼容,不会自动补全不足的空位,直接调用unpack解析就会报错。
解决方法
方法1:修改测试代码(推荐,不需要改依赖)
每次调用show()前,必须发送满当前灯带对应数量的像素数据,缺少的像素补0即可。你代码中前三次单独调用send_pixel的部分修改为如下逻辑:
#!/usr/bin/env perl use lib '../lib'; use Device::BlinkyTape::WS2811; # 初始化时明确指定灯带长度,避免模块默认值错误 my $bb = Device::BlinkyTape::WS2811->new(simulate => 1, led_count => 60); $bb->all_on(); sleep 2; $bb->all_off(); sleep 2; # 点亮第1个像素为白色,其余59个像素为黑色 $bb->send_pixel(255,255,255); for (1..59) { $bb->send_pixel(0,0,0); } $bb->show(); sleep 2; # 点亮第1个像素为红色,其余59个像素为黑色 $bb->send_pixel(255,0,0); for (1..59) { $bb->send_pixel(0,0,0); } $bb->show(); sleep 2; # 点亮第1个像素为暗红色,其余59个像素为黑色 $bb->send_pixel(240,0,0); for (1..59) { $bb->send_pixel(0,0,0); } $bb->show(); sleep 2; # 效果测试循环(原逻辑已经是发满60个像素,无需修改) for (my $b=0; $b<=1000; $b++) { for (my $a=0; $a<=59; $a++) { $bb->send_pixel(int(rand(254)),int(rand(254)),int(rand(254))); } $bb->show(); } sleep 2;
方法2:修复模块bug(如果不想修改业务代码)
找到报错提示的/home/pi/perl5/lib/perl5/Device/BlinkyTape/SimulationPort.pm文件,定位到第70行的unpack调用前,添加缓冲区补全逻辑:
# 按60个灯带的总长度180字节补全缓冲区,你可以根据自己的灯带长度修改数值 my $expect_length = $self->{led_count} * 3; $self->{buffer} .= "\x00" x ($expect_length - length($self->{buffer})) if length($self->{buffer}) < $expect_length; # 原有第70行的unpack逻辑放在这行后面
修改后模块会自动将不足长度的缓冲区补0,不会再出现解析越界的错误。
内容的提问来源于stack exchange,提问作者gatorreina
相关产品推荐
相关产品推荐

