Использование переменных класса Perl - PullRequest
3 голосов
/ 05 марта 2010

Я пытаюсь понять, как использовать переменную экземпляра в 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) Нужно ли конкретно undef в DESTROY? То есть Perl будет автоматически очищаться, даже если я не специально undef это?

Ответы [ 2 ]

9 голосов
/ 05 марта 2010

1) Разыменование ссылки перед ее вызовом:

${$dll_class->{MY_DLL}}->launch();

Используя \$, вы берете скалярную ссылку. ${...} является скалярным оператором .

Я не уверен, зачем вам вообще нужна ссылка на ссылку - вы можете просто установить 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 .

2 голосов
/ 05 марта 2010

Нет необходимости хранить ссылку на $my_dll, которая сама является ссылкой, возвращаемой Win32::OLE.

Написание метода доступа к нему сделает синтаксис более приятным и позволит вам изменить внутреннее устройство вашего класса без изменения кода, который его использует:

sub my_dll { $_[0]->{MY_DLL} }

Позже:

$object->my_dll->launch;

или, если @rjh отмечает в комментариях, что вы не хотите показывать дескриптор dll,

sub dll_launch {
   my $self = shift;
   $self->{MY_DLL}->launch();
   return;
}

и используйте

$object->dll_launch;

Далее, обратите внимание на следующее из Win32 :: OLE :

Обратите внимание на деструктор, указанный в методе Win32::OLE->new. Это гарантирует, что Excel будет корректно завершать работу, даже если программа Perl умирает. В противном случае может произойти утечка процесса, если ваше приложение умирает после открытия экземпляра OLE в Excel. Пользователь модуля должен убедиться, что все объекты OLE очищены должным образом!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...