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);
指向下列所述的線性化函數。
MRO 的名稱,以 ISO-8859-1 或 UTF-8 編碼。
名稱的長度。
如果名稱以 UTF-8 編碼,請將此設定為 HVhek_UTF8
。此值會直接傳遞為參數 kflags 至 hv_common()
。
MRO 名稱的預先計算雜湊值,或 0。
resolve
函數會被呼叫以使用此 MRO 為指定的儲存空間產生線性化的 ISA。它會以指向儲存空間的指標和 層級 0 被呼叫。核心在呼叫函數時總是將 層級 設定為 0 - 提供參數以允許實作在需要遞迴時追蹤深度。
此函數應傳回對包含字串 SV 的陣列的參考,其中包含父類別名稱的順序。類別名稱應為在儲存空間上呼叫 HvENAME()
的結果。在 HvENAME()
傳回 null 的情況下,應改用 HvNAME()
。
呼叫方負責增加傳回陣列的參考計數,如果它要保留結構。因此,如果您已建立暫時值且未保留任何指標,請使用 sv_2mortal()
以確保正確處置。如果您已快取傳回值,請傳回指向它的指標,而不要變更參考計數。
計算 MRO 可能很昂貴。此實作提供了一個快取,您可以在其中儲存單一的 SV *
,或任何可以轉換為 SV *
的東西,例如 AV *
。若要讀取您的私人值,請使用巨集 MRO_GET_PRIVATE_DATA()
,將其傳遞給快取中的 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()
Brandon L Black 編寫了 perl 核心中的 C3 MRO 和可切換 MRO 的實作。Nicholas Clark 建立了可插入式介面,將 Brandon 的實作重新整理為可與之搭配運作,並撰寫了這份文件。