9

我试图理解我继承的一些 XS 代码。我一直在尝试向调用 Perl 魔法的部分添加注释,但我找不到任何文档来帮助我理解这一行:

SvRMAGICAL_off((SV *) myVar);

RMAGICAL为了什么?使用 Perl 魔术变量时应该什么时候打开或关闭?

更新

Perlguts Illustrated 非常有趣,并且有一点关于 RMAGICAL 的信息(“R”代表“随机”),但它没有说明什么时候该弄乱它:http ://cpansearch.perl.org/src/ RURBAN/illguts-0.42/index.html

4

2 回答 2

6

它是一个标志,指示变量是否具有“清除”魔法,当变量被清除时(例如,当它被销毁时)应该调用魔法。mg_clear当一个人尝试做类似的事情时,它会被调用

undef %hash;
delete $a[4];
etc

它是由它计算的派生信息mg_magical,绝对不能被触及。mg_magical当魔术被添加到变量中或从变量中删除时,将被调用以更新标志。如果附加到标量的任何魔法在其魔法虚拟表中具有“清除”处理程序,则标量将设置为 RMAGICAL。否则,它会被关闭。实际上,这会缓存信息以使 Perl 免于重复检查附加到标量的所有魔法以获取此信息。

使用 clear magic 的一个示例:当清除 %SIG 条目时,magic 会删除该信号的信号处理程序。


这是mg_magical

void
Perl_mg_magical(pTHX_ SV *sv)
{
    const MAGIC* mg;
    PERL_ARGS_ASSERT_MG_MAGICAL;
    PERL_UNUSED_CONTEXT;

    SvMAGICAL_off(sv);
    if ((mg = SvMAGIC(sv))) {
        do {
            const MGVTBL* const vtbl = mg->mg_virtual;
            if (vtbl) {
                if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
                    SvGMAGICAL_on(sv);
                if (vtbl->svt_set)
                    SvSMAGICAL_on(sv);
                if (vtbl->svt_clear)
                    SvRMAGICAL_on(sv);
            }
        } while ((mg = mg->mg_moremagic));
        if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)))
            SvRMAGICAL_on(sv);
    }
}
于 2013-05-13T20:11:55.070 回答
4

SVs_RMG标志(用于SvRMAGICAL测试和设置/清除的内容SvRMAGICAL_on/SvRMAGICAL_off)意味着该变量具有与它相关的一些魔法,而不是魔法 getter 方法(由SVs_GMG标志指示)和魔法 setter 方法(由 指示SVs_SMG)。

在这里,我已经超出了我的深度,但是RMAGIC打开的变量示例包括大多数值%ENV(程序开始时设置的值,但不是您在运行时定义的值),%!%SIG, 和命名子程序的存储值(即,在程序中

 package main;
 sub foo { 42 }

$::{"foo"}是 RMAGICAL 而$::{"bar"}不是)。使用Devel::Peek有点,但对这种魔法可能是什么并不完全有启发性:

$ /usr/bin/perl -MDevel::Peek -e 'Dump $ENV{HOSTNAME}'
SV = PVMG(0x8003e910) at 0x800715f0
  REFCNT = 1
  FLAGS = (SMG,RMG,POK,pPOK)
  IV = 0
  NV = 0
  PV = 0x80072790 "localhost"\0
  CUR = 10
  LEN = 12
  MAGIC = 0x800727a0
    MG_VIRTUAL = &PL_vtbl_envelem
    MG_TYPE = PERL_MAGIC_envelem(e)
    MG_LEN = 8
    MG_PTR = 0x800727c0 "HOSTNAME"

在这里,我们看到保存的标量$ENV{HOSTNAME}有一个MG_TYPEMG_VIRTUAL,它给你什么,但不是这个变量的魔法的方式和原因。在“常规”魔法变量上,这些通常是(总是?)PERL_MAGIC_sv&PL_vtbl_sv

$ /usr/bin/perl -MDevel::Peek -e 'Dump $='
SV = PVMG(0x8008e080) at 0x80071de8
  REFCNT = 1
  FLAGS = (GMG,SMG)
  IV = 0
  NV = 0
  PV = 0
  MAGIC = 0x80085aa8
    MG_VIRTUAL = &PL_vtbl_sv
    MG_TYPE = PERL_MAGIC_sv(\0)
    MG_OBJ = 0x80071d58
    MG_LEN = 1
    MG_PTR = 0x80081ad0 "="

在 perl 源代码中有一个地方SvRMAGICAL_off使用了 -perlio.cXS(XS_io_MODIFY_SCALAR_ATTRIBUTES).

XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
{
    dXSARGS;
    SV * const sv = SvRV(ST(1));
    AV * const av = newAV();
    MAGIC *mg;
    int count = 0;
    int i;
    sv_magic(sv, MUTABLE_SV(av), PERL_MAGIC_ext, NULL, 0);

    SvRMAGICAL_off(sv);

    mg = mg_find(sv, PERL_MAGIC_ext);
    mg->mg_virtual = &perlio_vtab;
    mg_magical(sv);
    Perl_warn(aTHX_ "attrib %" SVf, SVfARG(sv));
    for (i = 2; i < items; i++) {
    STRLEN len;
    const char * const name = SvPV_const(ST(i), len);
    SV * const layer = PerlIO_find_layer(aTHX_ name, len, 1);
    if (layer) {
        av_push(av, SvREFCNT_inc_simple_NN(layer));
    }
    else {
        ST(count) = ST(i);
        count++;
    }
    }
    SvREFCNT_dec(av);
    XSRETURN(count);
}

mg_find出于某种原因(再次,我超出了我的深度),他们希望在通话期间关闭魔法。

于 2013-05-13T19:54:20.973 回答