【问题标题】:RPi::Pin objects -- can they be destroyed? So that another one using that pin can be created?RPi::Pin 对象——它们可以被销毁吗?这样可以创建另一个使用该引脚的人吗?
【发布时间】:2020-03-01 05:13:22
【问题描述】:

RPi::Pin 对象——看起来它们无法正确销毁?

在这个 (perl) Test::More 测试片段中,我创建了一个 pin,使用它(我看着灯闪烁), 然后销毁 pin 对象并尝试创建另一个。如下所示失败。

subtest 'pin level reuse' => sub {
my $pinNumber = 4;
my $pin = $wpi->pin ($pinNumber);
$pin->mode (OUTPUT);

# Blink to show it's working
diag "Light will blink";
$pin->write(1); sleep (.2); $pin->write(0); sleep (.2);
$pin->write(1); sleep (.2); $pin->write(0);
pass ('link');

# Now, can I destroy the pin object?
$pin = 0;
pass ('delete pin');

# Now, new pin object?
$pin = $wpi->pin ($pinNumber);
$pin->mode (OUTPUT);
pass ('create new pin');

# Blink to show it's working
diag "Light will blink";
$pin->write(1); sleep (.2); $pin->write(0); sleep (.2);
$pin->write(1); sleep (.2); $pin->write(0);
pass ('link');
};                              # subtest 'pin level reuse'

这失败了:

# Subtest: pin level reuse
    # Light will blink
    ok 1 - link
    ok 2 - delete pin
    1..2
ok 6 - pin level reuse
not ok 7 # TODO & SKIP Reusing pins not working yet
# Looks like you planned 6 tests but ran 7.
sc@ordovik:~/repo $ t/Button-002-PI.t
2020/02/29 23:06:11 onPi 1
1..6
ok 1 - 'buttonInterruptQ' isa 'MCE::Shared::Object'
ok 2 - use RPi::WiringPi;
ok 3 - use RPi::Pin;
ok 4 - use Slideshow::Light;
ok 5 - use Slideshow::Button;
# Subtest: pin level reuse
    # Light will blink
    ok 1 - link
    ok 2 - delete pin

cleaned up, exiting...

original error:
pin 4 is already in use... can't create second object

这只是一个限制吗?还是我必须进行的其他 API 调用最终会释放引脚? (它们应该在 RPi::Pin 对象的析构函数中,如果是这样的话?)

【问题讨论】:

  • 你看过undef吗?
  • 查看上面的代码——你认为undef ($pin); 会产生与我使用的$pin = 0; 不同的结果吗?刚试了一下,不行;仍然失败并显示相同的消息。这是我所期望的;分配一个新值使旧的有资格进行垃圾收集,并且 undef 不应该做任何不同的事情(与文档不同),并且在我的测试中也不应该这样做。
  • 只要引用代码中使用的变量,它就会存在。您可以在新的上下文{ my $pin = $wpi->pin ($pinNumber); .... } 中创建一个同名的变量,它应该屏蔽以前同名的变量。如果您将 $pin 代码包装在 {} 中,则该变量将仅存在于该块内。
  • 是的,并且在(最后一个或唯一的)引用上分配零将使其不再存在。在内部范围内用词法变量掩盖它肯定行不通,它只会使它在内部范围内不可见,不会让它消失。
  • 变量 $pin 存在,但它不再包含对 pin 对象的引用。 pin 对象上的引用计数应该已经为零(因为没有对它的剩余引用)并且应该清理它——但它似乎没有释放它在物理 pin 上的一些潜在保留

标签: perl raspbian wiringpi


【解决方案1】:

RPi::WiringPi 对任意吹走引脚和其他设备非常敏感。它们都是在内部注册的,以防止坏事发生。我是抱着安全第一的心态写的。

例如,它具有内置检查功能,因此如果您尝试使用相同的 pin 号启动第二个脚本,则会失败。如果某个引脚被远处的脚本用于某事,您真的不想禁用和更改引脚的模式。您看到此错误是因为您尝试在同一脚本中重新使用已在使用的 pin。

此外,一旦您将RPi::Pin 对象设置为$pin,就不能随意将其设置为0,因为您现在已经炸毁了该对象的所有功能和数据。该对象是RPi::Pin 类型的对象。将其更改为 0 会将其设置为整数。

当$wpi 对象超出范围或调用clean() 时,它会将所有正在使用的引脚重置为调用脚本时的默认设置,并注销它们以供重复使用.

只销毁一个 pin 对象是不明智的,因为那样你不知道它处于什么状态。如果你想重复使用 pin:

$wpi->unregister_pin($pin);
$pin = $wpi->pin($pin_number);

然而,unregister_pin() 虽然是公开的,但更多的是内部事务。与其想删除一个 pin 并重新初始化它,不如只更改 live pin 上的模式或其他设置。从本质上讲,pin 几乎总是用于应用程序的完整运行,而不是每次运行都会生成和销毁多次的东西。

更好的是,对于单元测试,我将事物划分为小范围:

my $pin = 18;

{ # test 1
    my $wpi = RPi::WiringPi->new;
    my $pin = $wpi->pin($num);

    $pin->mode(OUTPUT);

    is $pin->mode, OUTPUT, "pin mode is output for pin $num";

    # end of scope; everything will be properly cleaned up and destroyed
}

{ # test 2
    my $wpi = RPi::WiringPi->new;
    my $pin = $wpi->pin($num);

    is $pin->mode, INPUT, "pin mode is input for pin $num";
}    

【讨论】:

    猜你喜欢
    • 2010-10-19
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 2011-04-29
    • 1970-01-01
    相关资源
    最近更新 更多