Eric Fossum
Eric Fossum

Reputation: 2461

Using modules with Perl

I am trying to make a library of functions for my oscilloscope, but I can't seem to get other module files to play nice.

What I have is here, except the Oscope.pm file. If it's needed I can upload it too.

test.pl

# Includes
use 5.012;
use Oscope;
use Oscope::Acquire;
use warnings;

# From Oscope.pm
my $scope = Oscope->new('port', 'COM3');

# From Oscope::Acquire.pm
$scope->QueryAcquire();

Oscope/Acquire.pm

package Oscope::Acquire;

use Oscope;
use parent 'Oscope';

sub QueryAcquire
{
   my ($self) = @_;
   # Oscope.pm
   my $message = $self->Send('ACQUIRE?');
   return();
}

1;

Output

Can't locate object method "QueryAcquire" via package "Oscope" at C:\Documents and Settings\ericfoss\My Documents\Slick\Perl\tests\Test.pl line 11.

Upvotes: 1

Views: 121

Answers (4)

Max Lybbert
Max Lybbert

Reputation: 20021

I'm not going to say this is a good idea. You apparently want Oscope::Aquire to monkey patch Oscope. That is possible, but I would recommend having Oscope::Acquire export a function that takes an Oscope parameter (more information on exporting):

Oscope/Acquire.pm

package Oscope::Acquire;
require Exporter 'import';
@EXPORT_OK = qw{QueryAcquire};

use Oscope;

sub QueryAcquire
{
    my ($oscope) = @_;
    my $message = $oscope->Send('ACQUIRE?');
    return $message;
}

1;

Which you would use:

use Oscope;
use Oscope::Acquire 'QueryAcquire';

my $oscope = Oscope->new();
print QueryAquire($oscope);

However, if you really want the $oscope->QueryAcquire() syntax, and you don't want to put it in Oscope itself, you can monkey patch the module. Perl documentation refers to this as modifying the module's symbol table through a typeglob and it's apparently deprecated ("The results of creating new symbol table entries directly ... are undefined and subject to change between releases of perl"):

Oscope/Acquire.pm

package Oscope::Acquire;

use Oscope;

*Oscope::QueryAcquire = sub {
    my ($self) = @_;
    my $message = $self->Send('ACQUIRE?');
    return $message;
}

1;

I should have read my own link more closely. It appears that the approved way of doing this is to simply add methods to the Oscope package inside the Oscope/Acquire.pm file ("You can define a subroutine outside its package by explicitly qualifying the name of the subroutine"):

package Oscope::Acquire;
use Oscope;

...

sub Oscope::QueryAcquire {
    my ($self) = @_;
    my $message = $self->Send('ACQUIRE?');
    return $message;
}

1;

That is, there's no need to the typeglob.

Upvotes: 0

alexmac
alexmac

Reputation: 239

Where are your lib packages, place your code there. You could also use

use lib "path"

Another explanation can be found here which answers require over lib.

Your area message says it all in that it can't find the function.

Upvotes: 0

Eric Fossum
Eric Fossum

Reputation: 2461

As the code stands you could just say $scope->Oscope::Acquire::QueryAcquire();, but to get the desired effect, you need to make it part of the package.

package Oscope;

sub QueryAcquire
{
   # Code here
}

1;

Upvotes: -2

ikegami
ikegami

Reputation: 385496

Oscope->new('port', 'COM3')

should be

Oscope::Acquire->new('port', 'COM3')

Upvotes: 6

Related Questions