Like Share Discussion Bookmark Smile

J.J. Huang   2021-06-15   Perl   瀏覽次數:

Perl - 第二十五章 | Perl 包和模塊

Perl 中每個包有一個單獨的符號表,定義語法為:

1
package mypack;

此語句定義一個名為 mypack 的包,在此後定義的所有變量和子程序的名字都存貯在該包關聯的符號表中,直到遇到另一個 package 語句為止。
每個符號表有其自己的一組變量、子程序名,各組名字是不相關的,因此可以在不同的包中使用相同的變量名,而代表的是不同的變量。
從一個包中訪問另外一個包的變量,可通過” 包名 + 雙冒號( :: ) + 變量名 “ 的方式指定。

存貯變量和子程序的名字的預設符號表是與名為 main 的包相關聯的。如果在程序裡定義了其它的包,當你想切換回去使用預設的符號表,可以重新指定main包:

1
package main;

接下來的程序就好像從沒定義過包一樣,變量和子程序的名字象通常那樣存貯。

以下範例中文件有 main 和 Foo 包。特殊變量 PACKAGE 用於輸出包名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl

# main 包
$i = 1;
print "包名 : " , __PACKAGE__ , " $i\n";

package Foo;
# Foo 包
$i = 10;
print "包名 : " , __PACKAGE__ , " $i\n";

package main;
# 重新指定 main 包
$i = 100;
print "包名 : " , __PACKAGE__ , " $i\n";
print "包名: " , __PACKAGE__ , " $Foo::i\n";

1;

執行以上程序,輸出結果為:

1
2
3
4
包名 : main 1
包名 : Foo 10
包名 : main 100
包名: main 10

BEGIN 和 END 模塊

Perl語言提供了兩個關鍵字:BEGIN,END。它們可以分別包含一組腳本,用於程序體運行前或者運行後的執行。

語法格式如下:

1
2
3
4
BEGIN { ... }
END { ... }
BEGIN { ... }
END { ... }
  • 每個 BEGIN 模塊在 Perl 腳本載入和編譯後但在其他語句執行前執行。
  • 每個 END 語句塊在解釋器退出前執行。
  • BEGIN 和 END 語句塊在創建 Perl 模塊時特別有用。

看個範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl

package Foo;
print "Begin 和 Block 範例\n";

BEGIN {
print "這是 BEGIN 語句塊\n"
}

END {
print "這是 END 語句塊\n"
}

1;

執行以上程序,輸出結果為:

1
2
3
這是 BEGIN 語句塊
Begin 和 Block 範例
這是 END 語句塊

什麼是 Perl 模塊?

Perl5 中用Perl包來創建模塊。
Perl 模塊是一個可重複使用的包,模塊的名字與包名相同,定義的文件後綴為 .pm。

以下我們定義了一個模塊 Foo.pm,程式碼如下所示:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl

package Foo;
sub bar {
print "Hello $_[0]\n"
}

sub blat {
print "World $_[0]\n"
}
1;

Perl 中關於模塊需要注意以下幾點:

  • 函數 require 和 use 將載入一個模塊。
  • @INC 是 Perl 內置的一個特殊數組,它包含指向庫例程所在位置的目錄路徑。
  • require 和 use 函數調用 eval 函數來執行程式碼。
  • 末尾 1; 執行返回 TRUE,這是必須的,否則返回錯誤。

Require 和 Use 函數

模塊可以通過 require 函數來調用,如下所示:

1
2
3
4
5
6
#!/usr/bin/perl

require Foo;

Foo::bar( "a" );
Foo::blat( "b" );

也可以通過 use 函數來引用:

1
2
3
4
5
6
#!/usr/bin/perl

use Foo;

bar( "a" );
blat( "b" );

我們注意到 require 引用需要使用包名指定函數,而 use 不需要,二者的主要區別在於:

  • require用於載入module或perl程序(.pm後綴可以省略,但.pl必須有)
  • Perl use語句是編譯時引入的,require是運行時引入的
  • Perl use引入模塊的同時,也引入了模塊的子模塊。而require則不能引入,要在重新聲明
  • USE是在當前預設的@INC裡面去尋找,一旦模塊不在@INC中的話,用USE是不可以引入的,但是require可以指定路徑
  • USE引用模塊時,如果模塊名稱中包含::雙冒號,該雙冒號將作為路徑分隔符,相當於Unix下的/或者Windows下的\。如:
1
use MyDirectory::MyModule

通過添加以下語句 use 模塊就可以從模塊中導出列表符號:

1
2
require Exporter;
@ISA = qw(Exporter);

@EXPORT數組包含預設導出的變量和函數的名字:

1
2
3
4
5
6
7
8
9
10
11
package Module;

require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(bar blat); # 預設導出的符號

sub bar { print "Hello $_[0]\n" }
sub blat { print "World $_[0]\n" }
sub splat { print "Not $_[0]\n" } # Not exported!

1;

創建 Perl 模塊

通過 Perl 分發自帶的工具 h2xs 可以很簡單的創建一個 Perl 模塊。

你可以在命令行模式鍵入 h2xs 來看看它的參數列表。

h2xs 語法格式:

1
$ h2xs -AX -n ModuleName

參數說明:

1
2
3
-A 忽略 autoload 機制
-X 忽略 XS 元素
-n 指定擴展模塊的名字

例如,如果你的模塊在 Person.pm 文件中,使用以下命令:

1
$ h2xs -AX -n Person

執行以上程序將輸出:

1
2
3
4
5
6
Writing Person/lib/Person.pm
Writing Person/Makefile.PL
Writing Person/README
Writing Person/t/Person.t
Writing Person/Changes
Writing Person/MANIFEST

Person 目錄下你可以看到新增加的目錄及文件說明:

  • README :這個文件包含一些安裝信息,模塊依賴性,版權信息等。
  • Changes :這個文件作為你的項目的修改日誌(changelog)文件。
  • Makefile.PL :這是標準的 Perl Makefile 構造器。用於創建 Makefile.PL 文件來編譯該模塊。
  • MANIFEST :本文件用於自動構建 tar.gz 類型的模塊版本分發。這樣你就可以把你的模塊拿到 CPAN 發布或者分發給其他人。它包含了你在這個項目中所有文件的列表。
  • Person.pm :這是主模塊文件,包含你的 mod_perl 句柄程式碼(handler code)。
  • Person.t :針對該模塊的一些測試腳本。預設情況下它只是檢查模塊的載入,你可以添加一些新的測試單元。
  • t/ :測試文件
  • lib/ :實際源碼存放的目錄

你可以使用 tar (Linux 上) 命令來將以上目錄打包為 Person.tar.gz。

安裝 Perl 模塊

我們可以對剛才壓縮的 Person.tar.gz 文件進行解壓安裝,執行步驟如下:

1
2
3
4
5
tar xvfz Person.tar.gz
cd Person
perl Makefile.PL
make
make install

首先運行 “perl Makefile.PL” 在當前目錄生成 Makefile;
然後運行 “make” 編譯並創建所需的庫文件;
之後用 “make test” 測試編譯結果是否正確;最後運行 “make install” 將庫文件安裝到系統目錄,至此整個編譯過程結束。


註:以上參考了
Tutorialspoint, Perl - Packages and Modules