似乎 CPAN 上的一些(很多?)模块部分是使用 XS 在 C 中实现的,如果需要,可以回退到纯 perl 实现。虽然这很聪明,但它显然会损害性能,我想知道它会发生,以便我可以解决问题。
有没有一种通用的方法来停止或检测这种类型的回退?
有关此行为的示例,请查看(非常方便)Date::Simple(代码片段)
似乎 CPAN 上的一些(很多?)模块部分是使用 XS 在 C 中实现的,如果需要,可以回退到纯 perl 实现。虽然这很聪明,但它显然会损害性能,我想知道它会发生,以便我可以解决问题。
有没有一种通用的方法来停止或检测这种类型的回退?
有关此行为的示例,请查看(非常方便)Date::Simple(代码片段)
任何解决方案都必须基于每个模块(因为决定使用哪个实现是由父模块本身做出的,而不是 Perl 中的某种机制)。在您引用的情况下,在 use 语句之后检查 $Date::Simple::NoXs 的值将告诉您是否正在使用 XS。
use Date::Simple;
die "not using XS for Date::Simple\n" if $Date::Simple::NoXs;
例如,要检测 Scalar::Util 是使用 XS 还是纯 Perl 版本,您必须检查 dualvar 函数是否存在。
use Scalar::Util;
die "not using XS for Scalar::Util\n" unless if @Scalar::Util::EXPORTFAIL;
这是一个非常好的功能请求。不幸的是,没有模块作者编写的程序,perl 不知道模块是否有 XS 或 Pure Perl (PP) 变体,以及引擎是否通过后备加载。
您提出的这个示例由于它们被打包在同一个发行版和模块中的效果而更加复杂,而且这一切都是在内部完成的。我会修补它以遵循 CPAN 约定:DateSimple
,它需要DateSimple::PP
并建议DateSimple::XS
. 就是这样Text::CSV
,其他人也是这样做的。此方法允许::XS
直接使用构造函数来强制使用XS
并且同时甚至不安装 pureperl 变体。Template::Stash
或者,您可以将它们打包在一起——这就是Template::Stash::XS
. 使任何东西统一的第一步是获得临时功能。
Moose::Role
如果所有模块都拉入提供了一些基本属性的模块,那么这种事情可以很容易地完成_xs_class_name
,_pp_class_name
和engine_override
。但是,同样,到目前为止,甚至没有种子统一的 API 来实现这一点。
有一种通用方法可以检测您的函数是 XSUB CV。只需检查 CV 的 XSUB 插槽是否返回非 NULL 指针。
例如检查 My::func
sub isxsub {
use B;
my $name = shift;
my $cv = B::svref_2object(\&$name);
return !!$cv->XSUB;
}