目錄

名稱

XSLoader - 動態載入 C 函式庫至 Perl 程式碼

版本

版本 0.32

語法

package YourPackage;
require XSLoader;

XSLoader::load(__PACKAGE__, $VERSION);

說明

此模組定義一個標準的簡化介面,用於許多平台上可用的動態連結機制。其主要目的是實作 Perl 模組的便宜自動動態載入。

如需更複雜的介面,請參閱 DynaLoaderDynaLoader 的許多(大部分)功能未在 XSLoader 中實作,例如 dl_load_flagsXSLoader 不會遵守。

DynaLoader 遷移

使用 DynaLoader 的典型模組會像這樣開始

package YourPackage;
require DynaLoader;

our @ISA = qw( OnePackage OtherPackage DynaLoader );
our $VERSION = '0.01';
__PACKAGE__->bootstrap($VERSION);

變更為

package YourPackage;
use XSLoader;

our @ISA = qw( OnePackage OtherPackage );
our $VERSION = '0.01';
XSLoader::load(__PACKAGE__, $VERSION);

換句話說:將 require DynaLoader 替換為 use XSLoader,從 @ISA 中移除 DynaLoader,將 bootstrap 變更為 XSLoader::load。別忘了在 XSLoader::load 行上加上套件名稱的引號,並在引數(上方的 $VERSION)之前加上逗號(,)。

當然,如果 @ISA 中只包含 DynaLoader,則根本不需要 @ISA 指定;此外,如果使用更向後相容的

use vars qw($VERSION @ISA);

則可以將此對 @ISA 的參照與 @ISA 指定一起移除。

如果在 bootstrap 行上未指定 $VERSION,最後一行會變成

XSLoader::load(__PACKAGE__);

在這種情況下,可以進一步簡化為

XSLoader::load();

因為 load 會使用 caller 來判斷套件。

向後相容的樣板

如果您想要兩全其美,則需要更複雜的樣板。

    package YourPackage;

    our @ISA = qw( OnePackage OtherPackage );
    our $VERSION = '0.01';
    eval {
       require XSLoader;
	XSLoader::load(__PACKAGE__, $VERSION);
       1;
    } or do {
       require DynaLoader;
       push @ISA, 'DynaLoader';
       __PACKAGE__->bootstrap($VERSION);
    };

由於我們將 use XSLoader 替換為 require,因此需要加上 XSLoader::load() 引數的括號,所以編譯器不知道存在 XSLoader::load() 函式。

此樣板使用低開銷的 XSLoader(如果存在);如果與沒有 XSLoader 的舊版 Perl 一起使用,它會改用 DynaLoader

初始化順序:早期 load()

如果 XSUB 函式只會從其他模組呼叫,請略過此部分;只有當您從模組中的程式碼呼叫 XSUB,或在 XS 檔案中有 BOOT: 區段(請參閱 perlxs 中的 "The BOOT: Keyword")時才閱讀。這裡描述的內容同樣適用於 DynaLoader 介面。

使用 XS 的足夠複雜的模組將同時具有 Perl 程式碼(定義在 YourPackage.pm 中)和 XS 程式碼(定義在 YourPackage.xs 中)。如果此 Perl 程式碼呼叫此 XS 程式碼,和/或此 XS 程式碼呼叫 Perl 程式碼,則應注意初始化順序。

呼叫 XSLoader::load()(或 bootstrap())會呼叫模組的 bootstrap 程式碼。對於由 xsubpp 建置的模組(幾乎所有模組),這會有三個副作用

因此,如果 .pm 檔案中的程式碼呼叫這些 XSUB,則在定義 Perl 程式碼之前安裝 XSUB 會很方便;例如,這會讓 XSUB 的原型對此 Perl 程式碼可見。或者,如果 BOOT: 區段呼叫 .pm 檔案中定義的 Perl 函式(或使用 Perl 變數),則必須在呼叫 XSLoader::load()(或 bootstrap())之前定義這些函式或變數。

第一種情況更為常見,因此將樣板重寫為

package YourPackage;
use XSLoader;
our ($VERSION, @ISA);

BEGIN {
   @ISA = qw( OnePackage OtherPackage );
   $VERSION = '0.01';

   # Put Perl code used in the BOOT: section here

   XSLoader::load(__PACKAGE__, $VERSION);
}

# Put Perl code making calls into XSUBs here

最複雜的情況

如果 BOOT: 區段和 Perl 程式碼的相互依賴性比這更複雜(例如,BOOT: 區段呼叫 Perl 函式,而 Perl 函式又呼叫具有原型的 XSUB),則完全移除 BOOT: 區段。用函式 onBOOT() 取代它,並像這樣呼叫它

package YourPackage;
use XSLoader;
our ($VERSION, @ISA);

BEGIN {
   @ISA = qw( OnePackage OtherPackage );
   $VERSION = '0.01';
   XSLoader::load(__PACKAGE__, $VERSION);
}

# Put Perl code used in onBOOT() function here; calls to XSUBs are
# prototype-checked.

onBOOT;

# Put Perl initialization code assuming that XS is initialized here

診斷

找不到 %s 符號在 %s 中

(F) 在擴充模組中找不到引導符號。

無法為模組 %s 載入 %s:%s

(F) 擴充模組的載入或初始化失敗。詳細錯誤如下。

載入 %s 後存在未定義的符號:%s

(W) 如訊息所述,儘管擴充模組已正確載入和初始化,但仍有一些符號保持未定義。未定義符號清單如下。

限制

為了盡可能減少開銷,只檢查一個可能的位置以找到擴充 DLL(此位置是 make install 會放置 DLL 的位置)。如果找不到,則會將 DLL 的搜尋透明委派給 DynaLoader,它會沿著 @INC 清單尋找 DLL。

特別是,這適用於用於測試尚未安裝的擴充的 @INC 結構。這表示執行已解除安裝的擴充可能比在 make install 之後執行相同的擴充開銷更大。

已知錯誤

以不帶任何引數呼叫 XSLoader::load() 的新簡化方式在 Perl 5.8.4 和 5.8.5 上無法使用。

錯誤

請透過 perlbug(1) 工具回報任何錯誤或功能要求。

另請參閱

DynaLoader

作者

Ilya Zakharevich 最初從 DynaLoader 中萃取出 XSLoader

CPAN 版本目前由 Sébastien Aperghis-Tramoni <sebastien@aperghis.net> 維護。

前一位維護者是 Michael G Schwern <schwern@pobox.com>。

版權和授權

版權所有 (C) 1990-2011 Larry Wall 等人。

此程式為自由軟體;您可以在與 Perl 相同的條款下重新散布或修改它。