XSLoader - 在 Perl 代码中动态加载 C 库
版本 0.32
package YourPackage;
require XSLoader;
XSLoader::load(__PACKAGE__, $VERSION);
此模块定义了一个标准的简化接口,用于访问许多平台上可用的动态链接机制。它的主要目的是实现 Perl 模块的廉价自动动态加载。
有关更复杂的接口,请参见 DynaLoader。DynaLoader
的许多(大多数)功能在 XSLoader
中未实现,例如 dl_load_flags
,XSLoader
不支持。
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);
换句话说:用 use XSLoader
替换 require DynaLoader
,从 @ISA
中删除 DynaLoader
,用 XSLoader::load
替换 bootstrap
。不要忘记在 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);
};
关于 XSLoader::load()
参数的括号是必要的,因为我们用 require
替换了 use XSLoader
,所以编译器不知道存在 XSLoader::load()
函数。
这个样板使用低开销的 XSLoader
(如果存在);如果与没有 XSLoader
的旧版 Perl 一起使用,它将回退到使用 DynaLoader
。
如果 XSUB 函数应该只从其他模块调用,请跳过本节;只有在从模块中的代码调用 XSUB 或在 XS 文件中存在 BOOT:
部分时才阅读它(参见 "perlxs 中的 BOOT: 关键字")。这里描述的内容同样适用于 DynaLoader 接口。
一个足够复杂的模块使用 XS 将同时拥有 Perl 代码(定义在 YourPackage.pm 中)和 XS 代码(定义在 YourPackage.xs 中)。如果此 Perl 代码调用此 XS 代码,或者此 XS 代码调用 Perl 代码,则应注意初始化顺序。
对 XSLoader::load()
(或 bootstrap()
)的调用会调用模块的引导代码。对于由 xsubpp 构建的模块(几乎所有模块),这有三个副作用
进行完整性检查以确保 .pm 和(已编译的).xs 部分的版本兼容。如果指定了 $VERSION
,则将其用于检查。如果没有指定,则默认为 $XS_VERSION // $VERSION
(在模块的命名空间中)
XSUB 从 Perl 变得可访问
如果 .xs 文件中存在 BOOT:
部分,则调用其中的代码。
因此,如果.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:
部分调用了调用带有原型的 XSUB 的 Perl 函数),则完全删除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
后相同的扩展的开销大得多。
在 Perl 5.8.4 和 5.8.5 上,使用完全没有参数的 XSLoader::load()
的新简化方法不起作用。
请使用 perlbug(1) 工具报告任何错误或功能请求。
Ilya Zakharevich 最初从 DynaLoader
中提取了 XSLoader
。
CPAN 版本目前由 Sébastien Aperghis-Tramoni <[email protected]> 维护。
之前的维护者是 Michael G Schwern <[email protected]>。
版权所有 (C) 1990-2011 Larry Wall 及其他。
本程序是自由软件;您可以在 Perl 本身的相同条款下重新发布和/或修改它。