CPAN上的一些(很多?)模块似乎部分使用XS在C中实现,如果需要,可以回退到纯perl实现。虽然这很聪明,但它显然会损害性能,我想知道它发生了,所以我可以解决问题。
是否有停止或检测此类后备的一般方法?
有关此行为的示例,请查看(非常方便)Date::Simple(code snippet)
答案 0 :(得分:6)
任何解决方案都必须基于每个模块(因为决定使用哪个实现由父模块本身,而不是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版本,您必须检查是否存在双变量函数。
use Scalar::Util;
die "not using XS for Scalar::Util\n" unless if @Scalar::Util::EXPORTFAIL;
答案 1 :(得分:5)
这是一个非常好的功能请求。不幸的是,如果模块作者没有编写程序,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来实现这一目标。
答案 2 :(得分:1)
通常有一种方法可以检测到您的函数是XSUB CV。 只需检查CV的XSUB插槽是否返回非NULL指针。
e.g。检查My :: func
sub isxsub {
use B;
my $name = shift;
my $cv = B::svref_2object(\&$name);
return !!$cv->XSUB;
}