内容

名称

perlmroapi - Perl 方法解析插件接口

描述

从 Perl 5.10.1 开始,有一个新接口用于插入和使用除默认值(线性深度优先搜索)之外的方法解析顺序。5.10.0 中添加的 C3 方法解析顺序已重新实现为一个插件,而无需更改其 Perl 空间接口。

每个插件都应通过提供以下结构注册自身

struct mro_alg {
    AV *(*resolve)(pTHX_ HV *stash, U32 level);
    const char *name;
    U16 length;
    U16 kflags;
    U32 hash;
};

并调用 Perl_mro_register

Perl_mro_register(aTHX_ &my_mro_alg);
resolve

指向线性化函数的指针,如下所述。

name

MRO 的名称,以 ISO-8859-1 或 UTF-8 编码。

length

名称的长度。

kflags

如果名称以 UTF-8 编码,则将其设置为 HVhek_UTF8。该值作为参数 kflags 直接传递给 hv_common()

hash

MRO 名称的预计算哈希值,或 0。

回调

resolve 函数被调用来使用此 MRO 为给定的 stash 生成线性 ISA。它使用指向 stash 的指针和 0 的级别进行调用。当核心调用你的函数时,它总是将级别设置为 0 - 提供该参数是为了允许你的实现跟踪深度,如果它需要递归的话。

该函数应返回对包含字符串 SV 的数组的引用,该数组按顺序提供父类的名称。类的名称应为在 stash 上调用 HvENAME() 的结果。在 HvENAME() 返回 null 的情况下,应使用 HvNAME() 代替。

调用方负责增加返回的数组的引用计数(如果它想保留该结构)。因此,如果你创建了一个不保留指向它的指针的临时值,则 sv_2mortal() 可确保正确处理它。如果你已缓存你的返回值,则返回指向它的指针,而不更改引用计数。

缓存

计算 MRO 可能很昂贵。该实现提供了一个缓存,你可以在其中存储一个 SV *,或任何可以强制转换为 SV * 的内容,例如 AV *。要读取你的私有值,请使用宏 MRO_GET_PRIVATE_DATA(),将 stash 中的 mro_meta 结构和指向你的 mro_alg 结构的指针传递给它

meta = HvMROMETA(stash);
private_sv = MRO_GET_PRIVATE_DATA(meta, &my_mro_alg);

要设置你的私有值,请调用 Perl_mro_set_private_data()

Perl_mro_set_private_data(aTHX_ meta, &c3_alg, private_sv);

私有数据缓存将获取对 private_sv 的引用的所有权,这与 hv_store() 获取你传递给它的值的引用的所有权的方式非常相似。

示例

有关 MRO 实现的示例,请参阅 ext/mro/mro.xs 中的 S_mro_get_linear_isa_c3()BOOT: 部分,以及 mro_core.c 中的 S_mro_get_linear_isa_dfs()

作者

perl 核心中的 C3 MRO 和可切换 MRO 的实现是由 Brandon L Black 编写的。Nicholas Clark 创建了可插拔接口,重构了 Brandon 的实现以使其与之配合使用,并编写了此文档。