我试图了解如何在Perl OO中使用实例变量 - 更具体地说,与外部资源结合使用。让我解释一下:
我们有一个DLL,它暴露了我想通过Perl API公开的一些功能。我使用Win32::OLE来访问此DLL。所以我的构造函数很简单:
package MY_CLASS;
use Win32::OLE;
sub new
{
my ($class) = @_;
# instantiate the dll control
my $my_dll = Win32::OLE->new("MY_DLL.Control");
my $self = {
MY_DLL => \$my_dll,
};
bless $self, $class or die "Can't bless $!";
return $self;
}
sub DESTROY
{
my ($self) = shift;
undef $sef->{MY_DLL};
}
如您所见,我正在为实例变量MY_DLL分配对$my_dll
的引用。我有几个问题:
1)如何调用实例变量,因为它指向引用。所以,换句话说,如何在实例化的dll上调用方法,如下所示:
my $dll_class = new MY_CLASS;
$dll_class->{MY_DLL}->launch();
假设launch()是dll公开的方法。但是由于{MY_DLL}指向一个引用,Perl抱怨这是可以理解的。语法是什么?
2)我是否需要在DESTROY中专门undef
?即使我没有特别undef
它,Perl会自动清理吗?
答案 0 :(得分:9)
1)在调用之前取消引用引用:
${$dll_class->{MY_DLL}}->launch();
使用\$
,您将获得标量参考。 ${...}
是标量 de 引用运算符。
我不确定为什么你需要使用对引用的引用 - 你可以简单地将MY_DLL设置为$my_dll
,因为它已经是一个引用:
# ...
my $self = {
MY_DLL => $my_dll, # note, the \ is no longer in front of $my_dll
};
# ...
然后你可以用原始语法调用它:
$dll_class->{MY_DLL}->launch();
2)Perl会自动清理没有引用指向它的任何东西。当您的对象被销毁时,\$my_dll
将不再有对它的引用,因此$my_dll
也不会,因此它将被自动销毁。
一般来说,只需要担心是否有指向自己的递归数据结构。在这些情况下,您使用DESTROY
手动中断链接;在您的情况下,您不需要将句柄显式设置为undef。
有关参考文献的更多信息,请参阅perlref。有关垃圾收集,DESTROY方法和循环引用的信息,请参阅perlobj的“Destructors”部分。
答案 1 :(得分:2)
无需存储对$my_dll
的引用,Win32::OLE
本身是sub my_dll { $_[0]->{MY_DLL} }
返回的引用。
为它编写一个访问器将使语法更加甜美,并允许您更改类的内部,而无需更改使用它的代码:
$object->my_dll->launch;
随后:
sub dll_launch {
my $self = shift;
$self->{MY_DLL}->launch();
return;
}
或者,如果在评论中注明@rjh,则不希望公开dll句柄,
$object->dll_launch;
并使用
Win32::OLE->new
此外,请注意以下Win32::OLE:
请注意{{1}}方法中指定的析构函数。它确保即使Perl程序死亡,Excel也会正常关闭。否则,如果您的应用程序在打开Excel的OLE实例后死亡,则可能存在进程泄漏。模块用户有责任确保正确清理所有OLE对象!